Chromium Code Reviews| 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 "modules/fetch/FetchManager.h" | 5 #include "modules/fetch/FetchManager.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include "bindings/core/v8/ExceptionState.h" | 8 #include "bindings/core/v8/ExceptionState.h" |
| 9 #include "bindings/core/v8/ScriptPromiseResolver.h" | 9 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 10 #include "bindings/core/v8/ScriptState.h" | 10 #include "bindings/core/v8/ScriptState.h" |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 185 m_updater(updater), | 185 m_updater(updater), |
| 186 m_response(response), | 186 m_response(response), |
| 187 m_loader(loader), | 187 m_loader(loader), |
| 188 m_integrityMetadata(integrityMetadata), | 188 m_integrityMetadata(integrityMetadata), |
| 189 m_url(url), | 189 m_url(url), |
| 190 m_finished(false) { | 190 m_finished(false) { |
| 191 m_reader = m_handle->obtainReader(this); | 191 m_reader = m_handle->obtainReader(this); |
| 192 } | 192 } |
| 193 | 193 |
| 194 void didGetReadable() override { | 194 void didGetReadable() override { |
| 195 ASSERT(m_reader); | 195 DCHECK(m_reader); |
| 196 ASSERT(m_loader); | 196 DCHECK(m_loader); |
| 197 ASSERT(m_response); | 197 DCHECK(m_response); |
| 198 | 198 |
| 199 WebDataConsumerHandle::Result r = WebDataConsumerHandle::Ok; | 199 WebDataConsumerHandle::Result r = WebDataConsumerHandle::Ok; |
| 200 while (r == WebDataConsumerHandle::Ok) { | 200 while (r == WebDataConsumerHandle::Ok) { |
| 201 const void* buffer; | 201 const void* buffer; |
| 202 size_t size; | 202 size_t size; |
| 203 r = m_reader->beginRead(&buffer, WebDataConsumerHandle::FlagNone, | 203 r = m_reader->beginRead(&buffer, WebDataConsumerHandle::FlagNone, |
| 204 &size); | 204 &size); |
| 205 if (r == WebDataConsumerHandle::Ok) { | 205 if (r == WebDataConsumerHandle::Ok) { |
| 206 m_buffer.append(static_cast<const char*>(buffer), size); | 206 m_buffer.append(static_cast<const char*>(buffer), size); |
| 207 m_reader->endRead(size); | 207 m_reader->endRead(size); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 301 m_finished(false), | 301 m_finished(false), |
| 302 m_responseHttpStatusCode(0), | 302 m_responseHttpStatusCode(0), |
| 303 m_integrityVerifier(nullptr), | 303 m_integrityVerifier(nullptr), |
| 304 m_didFinishLoading(false), | 304 m_didFinishLoading(false), |
| 305 m_isIsolatedWorld(isIsolatedWorld), | 305 m_isIsolatedWorld(isIsolatedWorld), |
| 306 m_executionContext(executionContext) { | 306 m_executionContext(executionContext) { |
| 307 m_urlList.push_back(request->url()); | 307 m_urlList.push_back(request->url()); |
| 308 } | 308 } |
| 309 | 309 |
| 310 FetchManager::Loader::~Loader() { | 310 FetchManager::Loader::~Loader() { |
| 311 ASSERT(!m_loader); | 311 DCHECK(!m_loader); |
| 312 } | 312 } |
| 313 | 313 |
| 314 DEFINE_TRACE(FetchManager::Loader) { | 314 DEFINE_TRACE(FetchManager::Loader) { |
| 315 visitor->trace(m_fetchManager); | 315 visitor->trace(m_fetchManager); |
| 316 visitor->trace(m_resolver); | 316 visitor->trace(m_resolver); |
| 317 visitor->trace(m_request); | 317 visitor->trace(m_request); |
| 318 visitor->trace(m_loader); | 318 visitor->trace(m_loader); |
| 319 visitor->trace(m_integrityVerifier); | 319 visitor->trace(m_integrityVerifier); |
| 320 visitor->trace(m_executionContext); | 320 visitor->trace(m_executionContext); |
| 321 } | 321 } |
| 322 | 322 |
| 323 void FetchManager::Loader::didReceiveRedirectTo(const KURL& url) { | 323 void FetchManager::Loader::didReceiveRedirectTo(const KURL& url) { |
| 324 m_urlList.push_back(url); | 324 m_urlList.push_back(url); |
| 325 } | 325 } |
| 326 | 326 |
| 327 void FetchManager::Loader::didReceiveResponse( | 327 void FetchManager::Loader::didReceiveResponse( |
| 328 unsigned long, | 328 unsigned long, |
| 329 const ResourceResponse& response, | 329 const ResourceResponse& response, |
| 330 std::unique_ptr<WebDataConsumerHandle> handle) { | 330 std::unique_ptr<WebDataConsumerHandle> handle) { |
| 331 ASSERT(handle); | 331 DCHECK(handle); |
| 332 // TODO(horo): This check could be false when we will use the response url | 332 // TODO(horo): This check could be false when we will use the response url |
| 333 // in service worker responses. (crbug.com/553535) | 333 // in service worker responses. (crbug.com/553535) |
| 334 DCHECK(response.url() == m_urlList.back()); | 334 DCHECK(response.url() == m_urlList.back()); |
| 335 ScriptState* scriptState = m_resolver->getScriptState(); | 335 ScriptState* scriptState = m_resolver->getScriptState(); |
| 336 ScriptState::Scope scope(scriptState); | 336 ScriptState::Scope scope(scriptState); |
| 337 | 337 |
| 338 if (response.url().protocolIs("blob") && response.httpStatusCode() == 404) { | 338 if (response.url().protocolIs("blob") && response.httpStatusCode() == 404) { |
| 339 // "If |blob| is null, return a network error." | 339 // "If |blob| is null, return a network error." |
| 340 // https://fetch.spec.whatwg.org/#concept-basic-fetch | 340 // https://fetch.spec.whatwg.org/#concept-basic-fetch |
| 341 performNetworkError("Blob not found."); | 341 performNetworkError("Blob not found."); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 if (locations.size() > 1) { | 454 if (locations.size() > 1) { |
| 455 performNetworkError("Multiple Location header."); | 455 performNetworkError("Multiple Location header."); |
| 456 return; | 456 return; |
| 457 } | 457 } |
| 458 if (locations.size() == 1) { | 458 if (locations.size() == 1) { |
| 459 KURL locationURL(m_request->url(), locations[0]); | 459 KURL locationURL(m_request->url(), locations[0]); |
| 460 if (!locationURL.isValid()) { | 460 if (!locationURL.isValid()) { |
| 461 performNetworkError("Invalid Location header."); | 461 performNetworkError("Invalid Location header."); |
| 462 return; | 462 return; |
| 463 } | 463 } |
| 464 ASSERT(m_request->redirect() == WebURLRequest::FetchRedirectModeManual); | 464 DCHECK(m_request->redirect() == WebURLRequest::FetchRedirectModeManual); |
|
tkent
2017/04/08 02:29:54
Use DCHECK_EQ if it doesn't cause a build failure.
| |
| 465 taintedResponse = responseData->createOpaqueRedirectFilteredResponse(); | 465 taintedResponse = responseData->createOpaqueRedirectFilteredResponse(); |
| 466 } | 466 } |
| 467 // When the location header doesn't exist, we don't treat the response | 467 // When the location header doesn't exist, we don't treat the response |
| 468 // as a redirect response, and execute tainting. | 468 // as a redirect response, and execute tainting. |
| 469 } | 469 } |
| 470 if (!taintedResponse) { | 470 if (!taintedResponse) { |
| 471 switch (tainting) { | 471 switch (tainting) { |
| 472 case FetchRequestData::BasicTainting: | 472 case FetchRequestData::BasicTainting: |
| 473 taintedResponse = responseData->createBasicFilteredResponse(); | 473 taintedResponse = responseData->createBasicFilteredResponse(); |
| 474 break; | 474 break; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 495 // whose name is `Content-Type` and value is the MIME type and | 495 // whose name is `Content-Type` and value is the MIME type and |
| 496 // parameters returned from obtaining a resource" | 496 // parameters returned from obtaining a resource" |
| 497 r->headers()->headerList()->remove(HTTPNames::Access_Control_Allow_Origin); | 497 r->headers()->headerList()->remove(HTTPNames::Access_Control_Allow_Origin); |
| 498 } | 498 } |
| 499 r->headers()->setGuard(Headers::ImmutableGuard); | 499 r->headers()->setGuard(Headers::ImmutableGuard); |
| 500 | 500 |
| 501 if (m_request->integrity().isEmpty()) { | 501 if (m_request->integrity().isEmpty()) { |
| 502 m_resolver->resolve(r); | 502 m_resolver->resolve(r); |
| 503 m_resolver.clear(); | 503 m_resolver.clear(); |
| 504 } else { | 504 } else { |
| 505 ASSERT(!m_integrityVerifier); | 505 DCHECK(!m_integrityVerifier); |
| 506 m_integrityVerifier = | 506 m_integrityVerifier = |
| 507 new SRIVerifier(std::move(handle), sriConsumer, r, this, | 507 new SRIVerifier(std::move(handle), sriConsumer, r, this, |
| 508 m_request->integrity(), response.url()); | 508 m_request->integrity(), response.url()); |
| 509 } | 509 } |
| 510 } | 510 } |
| 511 | 511 |
| 512 void FetchManager::Loader::didFinishLoading(unsigned long, double) { | 512 void FetchManager::Loader::didFinishLoading(unsigned long, double) { |
| 513 m_didFinishLoading = true; | 513 m_didFinishLoading = true; |
| 514 // If there is an integrity verifier, and it has not already finished, it | 514 // If there is an integrity verifier, and it has not already finished, it |
| 515 // will take care of finishing the load or performing a network error when | 515 // will take care of finishing the load or performing a network error when |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 545 } | 545 } |
| 546 | 546 |
| 547 Document* FetchManager::Loader::document() const { | 547 Document* FetchManager::Loader::document() const { |
| 548 if (m_executionContext->isDocument()) { | 548 if (m_executionContext->isDocument()) { |
| 549 return toDocument(m_executionContext); | 549 return toDocument(m_executionContext); |
| 550 } | 550 } |
| 551 return nullptr; | 551 return nullptr; |
| 552 } | 552 } |
| 553 | 553 |
| 554 void FetchManager::Loader::loadSucceeded() { | 554 void FetchManager::Loader::loadSucceeded() { |
| 555 ASSERT(!m_failed); | 555 DCHECK(!m_failed); |
| 556 | 556 |
| 557 m_finished = true; | 557 m_finished = true; |
| 558 | 558 |
| 559 if (document() && document()->frame() && document()->frame()->page() && | 559 if (document() && document()->frame() && document()->frame()->page() && |
| 560 FetchUtils::isOkStatus(m_responseHttpStatusCode)) { | 560 FetchUtils::isOkStatus(m_responseHttpStatusCode)) { |
| 561 document()->frame()->page()->chromeClient().ajaxSucceeded( | 561 document()->frame()->page()->chromeClient().ajaxSucceeded( |
| 562 document()->frame()); | 562 document()->frame()); |
| 563 } | 563 } |
| 564 probe::didFinishFetch(m_executionContext, this, m_request->method(), | 564 probe::didFinishFetch(m_executionContext, this, m_request->method(), |
| 565 m_request->url().getString()); | 565 m_request->url().getString()); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 703 m_request->url().protocol() + "\" is not supported."); | 703 m_request->url().protocol() + "\" is not supported."); |
| 704 } | 704 } |
| 705 } | 705 } |
| 706 | 706 |
| 707 void FetchManager::Loader::performNetworkError(const String& message) { | 707 void FetchManager::Loader::performNetworkError(const String& message) { |
| 708 failed(message); | 708 failed(message); |
| 709 } | 709 } |
| 710 | 710 |
| 711 void FetchManager::Loader::performHTTPFetch(bool corsFlag, | 711 void FetchManager::Loader::performHTTPFetch(bool corsFlag, |
| 712 bool corsPreflightFlag) { | 712 bool corsPreflightFlag) { |
| 713 ASSERT( | 713 DCHECK( |
| 714 SchemeRegistry::shouldTreatURLSchemeAsSupportingFetchAPI( | 714 SchemeRegistry::shouldTreatURLSchemeAsSupportingFetchAPI( |
| 715 m_request->url().protocol()) || | 715 m_request->url().protocol()) || |
| 716 (m_request->url().protocolIs("blob") && !corsFlag && !corsPreflightFlag)); | 716 (m_request->url().protocolIs("blob") && !corsFlag && !corsPreflightFlag)); |
| 717 // CORS preflight fetch procedure is implemented inside | 717 // CORS preflight fetch procedure is implemented inside |
| 718 // DocumentThreadableLoader. | 718 // DocumentThreadableLoader. |
| 719 | 719 |
| 720 // "1. Let |HTTPRequest| be a copy of |request|, except that |HTTPRequest|'s | 720 // "1. Let |HTTPRequest| be a copy of |request|, except that |HTTPRequest|'s |
| 721 // body is a tee of |request|'s body." | 721 // body is a tee of |request|'s body." |
| 722 // We use ResourceRequest class for HTTPRequest. | 722 // We use ResourceRequest class for HTTPRequest. |
| 723 // FIXME: Support body. | 723 // FIXME: Support body. |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 842 ThreadableLoader::create(*m_executionContext, this, | 842 ThreadableLoader::create(*m_executionContext, this, |
| 843 threadableLoaderOptions, resourceLoaderOptions); | 843 threadableLoaderOptions, resourceLoaderOptions); |
| 844 m_loader->start(request); | 844 m_loader->start(request); |
| 845 } | 845 } |
| 846 | 846 |
| 847 // performDataFetch() is almost the same as performHTTPFetch(), except for: | 847 // performDataFetch() is almost the same as performHTTPFetch(), except for: |
| 848 // - We set AllowCrossOriginRequests to allow requests to data: URLs in | 848 // - We set AllowCrossOriginRequests to allow requests to data: URLs in |
| 849 // 'same-origin' mode. | 849 // 'same-origin' mode. |
| 850 // - We reject non-GET method. | 850 // - We reject non-GET method. |
| 851 void FetchManager::Loader::performDataFetch() { | 851 void FetchManager::Loader::performDataFetch() { |
| 852 ASSERT(m_request->url().protocolIsData()); | 852 DCHECK(m_request->url().protocolIsData()); |
| 853 | 853 |
| 854 ResourceRequest request(m_request->url()); | 854 ResourceRequest request(m_request->url()); |
| 855 request.setRequestContext(m_request->context()); | 855 request.setRequestContext(m_request->context()); |
| 856 request.setUseStreamOnResponse(true); | 856 request.setUseStreamOnResponse(true); |
| 857 request.setHTTPMethod(m_request->method()); | 857 request.setHTTPMethod(m_request->method()); |
| 858 request.setFetchRedirectMode(WebURLRequest::FetchRedirectModeError); | 858 request.setFetchRedirectMode(WebURLRequest::FetchRedirectModeError); |
| 859 // We intentionally skip 'setExternalRequestStateFromRequestorAddressSpace', | 859 // We intentionally skip 'setExternalRequestStateFromRequestorAddressSpace', |
| 860 // as 'data:' can never be external. | 860 // as 'data:' can never be external. |
| 861 | 861 |
| 862 ResourceLoaderOptions resourceLoaderOptions; | 862 ResourceLoaderOptions resourceLoaderOptions; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 932 m_loaders.erase(loader); | 932 m_loaders.erase(loader); |
| 933 loader->dispose(); | 933 loader->dispose(); |
| 934 } | 934 } |
| 935 | 935 |
| 936 DEFINE_TRACE(FetchManager) { | 936 DEFINE_TRACE(FetchManager) { |
| 937 visitor->trace(m_loaders); | 937 visitor->trace(m_loaders); |
| 938 ContextLifecycleObserver::trace(visitor); | 938 ContextLifecycleObserver::trace(visitor); |
| 939 } | 939 } |
| 940 | 940 |
| 941 } // namespace blink | 941 } // namespace blink |
| OLD | NEW |