| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "config.h" | |
| 6 #include "Request.h" | |
| 7 | |
| 8 #include "bindings/core/v8/Dictionary.h" | |
| 9 #include "core/dom/Document.h" | |
| 10 #include "core/dom/ExecutionContext.h" | |
| 11 #include "core/fetch/FetchUtils.h" | |
| 12 #include "core/fetch/ResourceLoaderOptions.h" | |
| 13 #include "core/loader/ThreadableLoader.h" | |
| 14 #include "modules/serviceworkers/FetchManager.h" | |
| 15 #include "modules/serviceworkers/RequestInit.h" | |
| 16 #include "platform/network/HTTPParsers.h" | |
| 17 #include "platform/network/ResourceRequest.h" | |
| 18 #include "platform/weborigin/Referrer.h" | |
| 19 #include "public/platform/WebServiceWorkerRequest.h" | |
| 20 #include "public/platform/WebURLRequest.h" | |
| 21 | |
| 22 namespace blink { | |
| 23 | |
| 24 FetchRequestData* createCopyOfFetchRequestDataForFetch(ExecutionContext* context
, const FetchRequestData* original) | |
| 25 { | |
| 26 FetchRequestData* request = FetchRequestData::create(); | |
| 27 request->setURL(original->url()); | |
| 28 request->setMethod(original->method()); | |
| 29 request->setHeaderList(original->headerList()->createCopy()); | |
| 30 request->setUnsafeRequestFlag(true); | |
| 31 request->setBlobDataHandle(original->blobDataHandle()); | |
| 32 // FIXME: Set client. | |
| 33 request->setOrigin(SecurityOrigin::create(context->url())); | |
| 34 // FIXME: Set ForceOriginHeaderFlag. | |
| 35 request->setSameOriginDataURLFlag(true); | |
| 36 request->mutableReferrer()->setClient(); | |
| 37 request->setContext(WebURLRequest::RequestContextFetch); | |
| 38 request->setMode(original->mode()); | |
| 39 request->setCredentials(original->credentials()); | |
| 40 // FIXME: Set cache mode. | |
| 41 return request; | |
| 42 } | |
| 43 | |
| 44 Request* Request::createRequestWithRequestOrString(ExecutionContext* context, Re
quest* inputRequest, const String& inputString, const RequestInit& init, Excepti
onState& exceptionState) | |
| 45 { | |
| 46 // "1. If input is a Request object, run these substeps:" | |
| 47 if (inputRequest) { | |
| 48 // "1. If input's used flag is set, throw a TypeError." | |
| 49 if (inputRequest->bodyUsed()) { | |
| 50 exceptionState.throwTypeError("Cannot construct a Request with a Req
uest object that has already been used."); | |
| 51 return 0; | |
| 52 } | |
| 53 // "2. Set input's used flag." | |
| 54 inputRequest->setBodyUsed(); | |
| 55 } | |
| 56 | |
| 57 // "2. Let |request| be |input|'s associated request, if |input| is a | |
| 58 // Request object, and a new request otherwise." | |
| 59 // "3. Set |request| to a new request whose url is |request|'s url, method | |
| 60 // is |request|'s method, header list is a copy of |request|'s header list, | |
| 61 // unsafe request flag is set, body is |request|'s body, client is entry | |
| 62 // settings object, origin is entry settings object's origin, force Origin | |
| 63 // header flag is set, same-origin data URL flag is set, referrer is client, | |
| 64 // context is fetch, mode is |request|'s mode, credentials mode is | |
| 65 // |request|'s credentials mode, and cache mode is |request|'s cache mode." | |
| 66 FetchRequestData* request = createCopyOfFetchRequestDataForFetch(context, in
putRequest ? inputRequest->request() : FetchRequestData::create()); | |
| 67 | |
| 68 // "4. Let |fallbackMode| be null." | |
| 69 // "5. Let |fallbackCredentials| be null." | |
| 70 // "6. Let |fallbackCache| be null." | |
| 71 // We don't use fallback values. We set these flags directly in below. | |
| 72 | |
| 73 // "7. If |input| is a string, run these substeps:" | |
| 74 if (!inputRequest) { | |
| 75 // "1. Let |parsedURL| be the result of parsing |input| with entry | |
| 76 // settings object's API base URL." | |
| 77 KURL parsedURL = context->completeURL(inputString); | |
| 78 // "2. If |parsedURL| is failure, throw a TypeError." | |
| 79 if (!parsedURL.isValid()) { | |
| 80 exceptionState.throwTypeError("Failed to parse URL from " + inputStr
ing); | |
| 81 return 0; | |
| 82 } | |
| 83 // "3. Set |request|'s url to |parsedURL|." | |
| 84 request->setURL(parsedURL); | |
| 85 // "4. Set |fallbackMode| to CORS." | |
| 86 // "5. Set |fallbackCredentials| to omit." | |
| 87 // "6. Set |fallbackCache| to default." | |
| 88 // We don't use fallback values. We set these flags directly in below. | |
| 89 } | |
| 90 | |
| 91 // "8. Let |mode| be |init|'s mode member if it is present, and | |
| 92 // |fallbackMode| otherwise." | |
| 93 // "9. If |mode| is non-null, set |request|'s mode to |mode|." | |
| 94 if (init.mode == "same-origin") { | |
| 95 request->setMode(WebURLRequest::FetchRequestModeSameOrigin); | |
| 96 } else if (init.mode == "no-cors") { | |
| 97 request->setMode(WebURLRequest::FetchRequestModeNoCORS); | |
| 98 } else if (init.mode == "cors") { | |
| 99 request->setMode(WebURLRequest::FetchRequestModeCORS); | |
| 100 } else { | |
| 101 if (!inputRequest) | |
| 102 request->setMode(WebURLRequest::FetchRequestModeCORS); | |
| 103 } | |
| 104 | |
| 105 // "10. Let |credentials| be |init|'s credentials member if it is present, | |
| 106 // and |fallbackCredentials| otherwise." | |
| 107 // "11. If |credentials| is non-null, set |request|'s credentials mode to | |
| 108 // |credentials|. | |
| 109 if (init.credentials == "omit") { | |
| 110 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); | |
| 111 } else if (init.credentials == "same-origin") { | |
| 112 request->setCredentials(WebURLRequest::FetchCredentialsModeSameOrigin); | |
| 113 } else if (init.credentials == "include") { | |
| 114 request->setCredentials(WebURLRequest::FetchCredentialsModeInclude); | |
| 115 } else { | |
| 116 if (!inputRequest) | |
| 117 request->setCredentials(WebURLRequest::FetchCredentialsModeOmit); | |
| 118 } | |
| 119 | |
| 120 // FIXME: "12. Let |cache| be |init|'s cache member if it is present, and | |
| 121 // |fallbackCache| otherwise." | |
| 122 // FIXME: "13. If |cache| is non-null, set |request|'s cache mode to | |
| 123 // |cache|." | |
| 124 | |
| 125 // "14. If |init|'s method member is present, let |method| be it and run | |
| 126 // these substeps:" | |
| 127 if (!init.method.isEmpty()) { | |
| 128 // "1. If |method| is not a method or method is a forbidden method, | |
| 129 // throw a TypeError." | |
| 130 if (!isValidHTTPToken(init.method)) { | |
| 131 exceptionState.throwTypeError("'" + init.method + "' is not a valid
HTTP method."); | |
| 132 return 0; | |
| 133 } | |
| 134 if (FetchUtils::isForbiddenMethod(init.method)) { | |
| 135 exceptionState.throwTypeError("'" + init.method + "' HTTP method is
unsupported."); | |
| 136 return 0; | |
| 137 } | |
| 138 // "2. Normalize |method|." | |
| 139 // "3. Set |request|'s method to |method|." | |
| 140 request->setMethod(FetchUtils::normalizeMethod(AtomicString(init.method)
)); | |
| 141 } | |
| 142 // "15. Let |r| be a new Request object associated with |request|, and a new | |
| 143 // Headers object." | |
| 144 Request* r = Request::create(context, request); | |
| 145 // "16. Let |headers| be a copy of |r|'s Headers object." | |
| 146 // "17. If |init|'s headers member is present, set |headers| to |init|'s | |
| 147 // headers member." | |
| 148 // We don't create a copy of r's Headers object when init's headers member | |
| 149 // is present. | |
| 150 Headers* headers = 0; | |
| 151 if (!init.headers && init.headersDictionary.isUndefinedOrNull()) { | |
| 152 headers = r->headers()->createCopy(); | |
| 153 } | |
| 154 // "18. Empty |r|'s request's header list." | |
| 155 r->clearHeaderList(); | |
| 156 // "19. If |r|'s request's mode is no CORS, run these substeps: | |
| 157 if (r->request()->mode() == WebURLRequest::FetchRequestModeNoCORS) { | |
| 158 // "1. If |r|'s request's method is not a simple method, throw a | |
| 159 // TypeError." | |
| 160 if (!FetchUtils::isSimpleMethod(r->request()->method())) { | |
| 161 exceptionState.throwTypeError("'" + r->request()->method() + "' is u
nsupported in no-cors mode."); | |
| 162 return 0; | |
| 163 } | |
| 164 // "Set |r|'s Headers object's guard to |request-no-CORS|. | |
| 165 r->headers()->setGuard(Headers::RequestNoCORSGuard); | |
| 166 } | |
| 167 // "20. Fill |r|'s Headers object with |headers|. Rethrow any exceptions." | |
| 168 if (init.headers) { | |
| 169 ASSERT(init.headersDictionary.isUndefinedOrNull()); | |
| 170 r->headers()->fillWith(init.headers.get(), exceptionState); | |
| 171 } else if (!init.headersDictionary.isUndefinedOrNull()) { | |
| 172 r->headers()->fillWith(init.headersDictionary, exceptionState); | |
| 173 } else { | |
| 174 ASSERT(headers); | |
| 175 r->headers()->fillWith(headers, exceptionState); | |
| 176 } | |
| 177 if (exceptionState.hadException()) | |
| 178 return 0; | |
| 179 | |
| 180 // "21. If |init|'s body member is present, run these substeps:" | |
| 181 if (init.bodyBlobHandle) { | |
| 182 // "1. Let |stream| and |Content-Type| be the result of extracting | |
| 183 // |init|'s body member." | |
| 184 // "2. Set |r|'s request's body to |stream|." | |
| 185 // "3.If |Content-Type| is non-null and |r|'s request's header list | |
| 186 // contains no header named `Content-Type`, append | |
| 187 // `Content-Type`/|Content-Type| to |r|'s Headers object. Rethrow any | |
| 188 // exception." | |
| 189 r->setBodyBlobHandle(init.bodyBlobHandle); | |
| 190 if (!init.bodyBlobHandle->type().isEmpty() && !r->headers()->has("Conten
t-Type", exceptionState)) { | |
| 191 r->headers()->append("Content-Type", init.bodyBlobHandle->type(), ex
ceptionState); | |
| 192 } | |
| 193 if (exceptionState.hadException()) | |
| 194 return 0; | |
| 195 } | |
| 196 // "22. Set |r|'s MIME type to the result of extracting a MIME type from | |
| 197 // |r|'s request's header list." | |
| 198 // FIXME: We don't have MIME type in Request object yet. | |
| 199 | |
| 200 // "23. Return |r|." | |
| 201 return r; | |
| 202 } | |
| 203 | |
| 204 Request* Request::create(ExecutionContext* context, const RequestInfo& input, co
nst Dictionary& init, ExceptionState& exceptionState) | |
| 205 { | |
| 206 ASSERT(!input.isNull()); | |
| 207 if (input.isUSVString()) | |
| 208 return create(context, input.getAsUSVString(), init, exceptionState); | |
| 209 return create(context, input.getAsRequest(), init, exceptionState); | |
| 210 } | |
| 211 | |
| 212 Request* Request::create(ExecutionContext* context, const String& input, Excepti
onState& exceptionState) | |
| 213 { | |
| 214 return create(context, input, Dictionary(), exceptionState); | |
| 215 } | |
| 216 | |
| 217 Request* Request::create(ExecutionContext* context, const String& input, const D
ictionary& init, ExceptionState& exceptionState) | |
| 218 { | |
| 219 return createRequestWithRequestOrString(context, 0, input, RequestInit(conte
xt, init, exceptionState), exceptionState); | |
| 220 } | |
| 221 | |
| 222 Request* Request::create(ExecutionContext* context, Request* input, ExceptionSta
te& exceptionState) | |
| 223 { | |
| 224 return create(context, input, Dictionary(), exceptionState); | |
| 225 } | |
| 226 | |
| 227 Request* Request::create(ExecutionContext* context, Request* input, const Dictio
nary& init, ExceptionState& exceptionState) | |
| 228 { | |
| 229 return createRequestWithRequestOrString(context, input, String(), RequestIni
t(context, init, exceptionState), exceptionState); | |
| 230 } | |
| 231 | |
| 232 Request* Request::create(ExecutionContext* context, FetchRequestData* request) | |
| 233 { | |
| 234 Request* r = new Request(context, request); | |
| 235 r->suspendIfNeeded(); | |
| 236 return r; | |
| 237 } | |
| 238 | |
| 239 Request::Request(ExecutionContext* context, FetchRequestData* request) | |
| 240 : Body(context) | |
| 241 , m_request(request) | |
| 242 , m_headers(Headers::create(m_request->headerList())) | |
| 243 { | |
| 244 m_headers->setGuard(Headers::RequestGuard); | |
| 245 } | |
| 246 | |
| 247 Request* Request::create(ExecutionContext* context, const WebServiceWorkerReques
t& webRequest) | |
| 248 { | |
| 249 Request* r = new Request(context, webRequest); | |
| 250 r->suspendIfNeeded(); | |
| 251 return r; | |
| 252 } | |
| 253 | |
| 254 Request* Request::create(const Request& copyFrom) | |
| 255 { | |
| 256 Request* r = new Request(copyFrom); | |
| 257 r->suspendIfNeeded(); | |
| 258 return r; | |
| 259 } | |
| 260 | |
| 261 Request::Request(ExecutionContext* context, const WebServiceWorkerRequest& webRe
quest) | |
| 262 : Body(context) | |
| 263 , m_request(FetchRequestData::create(webRequest)) | |
| 264 , m_headers(Headers::create(m_request->headerList())) | |
| 265 { | |
| 266 m_headers->setGuard(Headers::RequestGuard); | |
| 267 } | |
| 268 | |
| 269 Request::Request(const Request& copy_from) | |
| 270 : Body(copy_from) | |
| 271 , m_request(copy_from.m_request->createCopy()) | |
| 272 , m_headers(Headers::create(m_request->headerList())) | |
| 273 { | |
| 274 } | |
| 275 | |
| 276 | |
| 277 String Request::method() const | |
| 278 { | |
| 279 // "The method attribute's getter must return request's method." | |
| 280 return m_request->method(); | |
| 281 } | |
| 282 | |
| 283 String Request::url() const | |
| 284 { | |
| 285 // The url attribute's getter must return request's url, serialized with the
exclude fragment flag set. | |
| 286 if (!m_request->url().hasFragmentIdentifier()) | |
| 287 return m_request->url(); | |
| 288 KURL url(m_request->url()); | |
| 289 url.removeFragmentIdentifier(); | |
| 290 return url; | |
| 291 } | |
| 292 | |
| 293 String Request::referrer() const | |
| 294 { | |
| 295 // "The referrer attribute's getter must return the empty string if | |
| 296 // request's referrer is no referrer, "about:client" if request's referrer | |
| 297 // is client and request's referrer, serialized, otherwise." | |
| 298 if (m_request->referrer().isNoReferrer()) | |
| 299 return String(); | |
| 300 if (m_request->referrer().isClient()) | |
| 301 return String("about:client"); | |
| 302 return m_request->referrer().referrer().referrer; | |
| 303 } | |
| 304 | |
| 305 String Request::mode() const | |
| 306 { | |
| 307 // "The mode attribute's getter must return the value corresponding to the | |
| 308 // first matching statement, switching on request's mode:" | |
| 309 switch (m_request->mode()) { | |
| 310 case WebURLRequest::FetchRequestModeSameOrigin: | |
| 311 return "same-origin"; | |
| 312 case WebURLRequest::FetchRequestModeNoCORS: | |
| 313 return "no-cors"; | |
| 314 case WebURLRequest::FetchRequestModeCORS: | |
| 315 case WebURLRequest::FetchRequestModeCORSWithForcedPreflight: | |
| 316 return "cors"; | |
| 317 } | |
| 318 ASSERT_NOT_REACHED(); | |
| 319 return ""; | |
| 320 } | |
| 321 | |
| 322 String Request::credentials() const | |
| 323 { | |
| 324 // "The credentials attribute's getter must return the value corresponding | |
| 325 // to the first matching statement, switching on request's credentials | |
| 326 // mode:" | |
| 327 switch (m_request->credentials()) { | |
| 328 case WebURLRequest::FetchCredentialsModeOmit: | |
| 329 return "omit"; | |
| 330 case WebURLRequest::FetchCredentialsModeSameOrigin: | |
| 331 return "same-origin"; | |
| 332 case WebURLRequest::FetchCredentialsModeInclude: | |
| 333 return "include"; | |
| 334 } | |
| 335 ASSERT_NOT_REACHED(); | |
| 336 return ""; | |
| 337 } | |
| 338 | |
| 339 Request* Request::clone(ExceptionState& exceptionState) const | |
| 340 { | |
| 341 if (bodyUsed()) { | |
| 342 exceptionState.throwTypeError("Request body is already used"); | |
| 343 return nullptr; | |
| 344 } | |
| 345 if (streamAccessed()) { | |
| 346 // FIXME: Support clone() of the stream accessed Request. | |
| 347 exceptionState.throwTypeError("clone() of the Request which .body is acc
essed is not supported."); | |
| 348 return nullptr; | |
| 349 } | |
| 350 return Request::create(*this); | |
| 351 } | |
| 352 | |
| 353 void Request::populateWebServiceWorkerRequest(WebServiceWorkerRequest& webReques
t) const | |
| 354 { | |
| 355 webRequest.setMethod(method()); | |
| 356 webRequest.setURL(m_request->url()); | |
| 357 | |
| 358 const FetchHeaderList* headerList = m_headers->headerList(); | |
| 359 for (size_t i = 0, size = headerList->size(); i < size; ++i) { | |
| 360 const FetchHeaderList::Header& header = headerList->entry(i); | |
| 361 webRequest.appendHeader(header.first, header.second); | |
| 362 } | |
| 363 | |
| 364 webRequest.setReferrer(m_request->referrer().referrer().referrer, static_cas
t<WebReferrerPolicy>(m_request->referrer().referrer().referrerPolicy)); | |
| 365 // 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 | |
| 366 // to plumb this information in to here. | |
| 367 } | |
| 368 | |
| 369 void Request::setBodyBlobHandle(PassRefPtr<BlobDataHandle> blobDataHandle) | |
| 370 { | |
| 371 m_request->setBlobDataHandle(blobDataHandle); | |
| 372 } | |
| 373 | |
| 374 void Request::clearHeaderList() | |
| 375 { | |
| 376 m_request->headerList()->clearList(); | |
| 377 } | |
| 378 | |
| 379 PassRefPtr<BlobDataHandle> Request::blobDataHandle() const | |
| 380 { | |
| 381 return m_request->blobDataHandle(); | |
| 382 } | |
| 383 | |
| 384 BodyStreamBuffer* Request::buffer() const | |
| 385 { | |
| 386 return nullptr; | |
| 387 } | |
| 388 | |
| 389 String Request::contentTypeForBuffer() const | |
| 390 { | |
| 391 // We don't support BodyStreamBuffer for Request yet. | |
| 392 ASSERT_NOT_REACHED(); | |
| 393 return String(); | |
| 394 } | |
| 395 | |
| 396 void Request::trace(Visitor* visitor) | |
| 397 { | |
| 398 Body::trace(visitor); | |
| 399 visitor->trace(m_request); | |
| 400 visitor->trace(m_headers); | |
| 401 } | |
| 402 | |
| 403 } // namespace blink | |
| OLD | NEW |