| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2011, 2012 Google Inc. All rights reserved. |
| 3 * Copyright (C) 2013, Intel Corporation | 3 * Copyright (C) 2013, Intel Corporation |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 DCHECK(!resource()); | 315 DCHECK(!resource()); |
| 316 | 316 |
| 317 // Cross-origin requests are only allowed certain registered schemes. We would | 317 // Cross-origin requests are only allowed certain registered schemes. We would |
| 318 // catch this when checking response headers later, but there is no reason to | 318 // catch this when checking response headers later, but there is no reason to |
| 319 // send a request, preflighted or not, that's guaranteed to be denied. | 319 // send a request, preflighted or not, that's guaranteed to be denied. |
| 320 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled( | 320 if (!SchemeRegistry::shouldTreatURLSchemeAsCORSEnabled( |
| 321 request.url().protocol())) { | 321 request.url().protocol())) { |
| 322 InspectorInstrumentation:: | 322 InspectorInstrumentation:: |
| 323 documentThreadableLoaderFailedToStartLoadingForClient(m_document, | 323 documentThreadableLoaderFailedToStartLoadingForClient(m_document, |
| 324 m_client); | 324 m_client); |
| 325 ThreadableLoaderClient* client = m_client; | 325 dispatchDidFailAccessControlCheck(ResourceError( |
| 326 clear(); | |
| 327 client->didFailAccessControlCheck(ResourceError( | |
| 328 errorDomainBlinkInternal, 0, request.url().getString(), | 326 errorDomainBlinkInternal, 0, request.url().getString(), |
| 329 "Cross origin requests are only supported for protocol schemes: " + | 327 "Cross origin requests are only supported for protocol schemes: " + |
| 330 SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); | 328 SchemeRegistry::listOfCORSEnabledURLSchemes() + ".")); |
| 331 return; | 329 return; |
| 332 } | 330 } |
| 333 | 331 |
| 334 // Non-secure origins may not make "external requests": | 332 // Non-secure origins may not make "external requests": |
| 335 // https://mikewest.github.io/cors-rfc1918/#integration-fetch | 333 // https://mikewest.github.io/cors-rfc1918/#integration-fetch |
| 336 if (!document().isSecureContext() && request.isExternalRequest()) { | 334 if (!document().isSecureContext() && request.isExternalRequest()) { |
| 337 ThreadableLoaderClient* client = m_client; | 335 dispatchDidFailAccessControlCheck( |
| 338 clear(); | |
| 339 client->didFailAccessControlCheck( | |
| 340 ResourceError(errorDomainBlinkInternal, 0, request.url().getString(), | 336 ResourceError(errorDomainBlinkInternal, 0, request.url().getString(), |
| 341 "Requests to internal network resources are not allowed " | 337 "Requests to internal network resources are not allowed " |
| 342 "from non-secure contexts (see https://goo.gl/Y0ZkNV). " | 338 "from non-secure contexts (see https://goo.gl/Y0ZkNV). " |
| 343 "This is an experimental restriction which is part of " | 339 "This is an experimental restriction which is part of " |
| 344 "'https://mikewest.github.io/cors-rfc1918/'.")); | 340 "'https://mikewest.github.io/cors-rfc1918/'.")); |
| 345 return; | 341 return; |
| 346 } | 342 } |
| 347 | 343 |
| 348 ResourceRequest crossOriginRequest(request); | 344 ResourceRequest crossOriginRequest(request); |
| 349 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); | 345 ResourceLoaderOptions crossOriginOptions(m_resourceLoaderOptions); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 432 if (timeoutMilliseconds) { | 428 if (timeoutMilliseconds) { |
| 433 double elapsedTime = | 429 double elapsedTime = |
| 434 monotonicallyIncreasingTime() - m_requestStartedSeconds; | 430 monotonicallyIncreasingTime() - m_requestStartedSeconds; |
| 435 double nextFire = timeoutMilliseconds / 1000.0; | 431 double nextFire = timeoutMilliseconds / 1000.0; |
| 436 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); | 432 double resolvedTime = std::max(nextFire - elapsedTime, 0.0); |
| 437 m_timeoutTimer.startOneShot(resolvedTime, BLINK_FROM_HERE); | 433 m_timeoutTimer.startOneShot(resolvedTime, BLINK_FROM_HERE); |
| 438 } | 434 } |
| 439 } | 435 } |
| 440 | 436 |
| 441 void DocumentThreadableLoader::cancel() { | 437 void DocumentThreadableLoader::cancel() { |
| 442 cancelWithError(ResourceError()); | 438 // Cancel can re-enter, and therefore |resource()| might be null here as a |
| 443 } | 439 // result. |
| 444 | |
| 445 void DocumentThreadableLoader::cancelWithError(const ResourceError& error) { | |
| 446 // Cancel can re-enter and m_resource might be null here as a result. | |
| 447 if (!m_client || !resource()) { | 440 if (!m_client || !resource()) { |
| 448 clear(); | 441 clear(); |
| 449 return; | 442 return; |
| 450 } | 443 } |
| 451 | 444 |
| 452 ResourceError errorForCallback = error; | 445 // FIXME: This error is sent to the client in didFail(), so it should not be |
| 453 if (errorForCallback.isNull()) { | 446 // an internal one. Use FrameLoaderClient::cancelledError() instead. |
| 454 // FIXME: This error is sent to the client in didFail(), so it should not be | 447 ResourceError error(errorDomainBlinkInternal, 0, resource()->url(), |
| 455 // an internal one. Use FrameLoaderClient::cancelledError() instead. | 448 "Load cancelled"); |
| 456 errorForCallback = | 449 error.setIsCancellation(true); |
| 457 ResourceError(errorDomainBlinkInternal, 0, | |
| 458 resource()->url().getString(), "Load cancelled"); | |
| 459 errorForCallback.setIsCancellation(true); | |
| 460 } | |
| 461 | 450 |
| 462 ThreadableLoaderClient* client = m_client; | 451 dispatchDidFail(error); |
| 463 clear(); | |
| 464 client->didFail(errorForCallback); | |
| 465 } | 452 } |
| 466 | 453 |
| 467 void DocumentThreadableLoader::setDefersLoading(bool value) { | 454 void DocumentThreadableLoader::setDefersLoading(bool value) { |
| 468 if (resource()) | 455 if (resource()) |
| 469 resource()->setDefersLoading(value); | 456 resource()->setDefersLoading(value); |
| 470 } | 457 } |
| 471 | 458 |
| 472 void DocumentThreadableLoader::clear() { | 459 void DocumentThreadableLoader::clear() { |
| 473 m_client = nullptr; | 460 m_client = nullptr; |
| 474 m_timeoutTimer.stop(); | 461 m_timeoutTimer.stop(); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 573 // request was not same-origin. | 560 // request was not same-origin. |
| 574 accessControlErrorDescription = | 561 accessControlErrorDescription = |
| 575 "Redirect from '" + redirectResponse.url().getString() + "' to '" + | 562 "Redirect from '" + redirectResponse.url().getString() + "' to '" + |
| 576 request.url().getString() + "' has been blocked by CORS policy: " + | 563 request.url().getString() + "' has been blocked by CORS policy: " + |
| 577 accessControlErrorDescription; | 564 accessControlErrorDescription; |
| 578 } else { | 565 } else { |
| 579 allowRedirect = true; | 566 allowRedirect = true; |
| 580 } | 567 } |
| 581 | 568 |
| 582 if (!allowRedirect) { | 569 if (!allowRedirect) { |
| 583 ThreadableLoaderClient* client = m_client; | 570 dispatchDidFailAccessControlCheck(ResourceError( |
| 584 clear(); | |
| 585 client->didFailAccessControlCheck(ResourceError( | |
| 586 errorDomainBlinkInternal, 0, redirectResponse.url().getString(), | 571 errorDomainBlinkInternal, 0, redirectResponse.url().getString(), |
| 587 accessControlErrorDescription)); | 572 accessControlErrorDescription)); |
| 588 return false; | 573 return false; |
| 589 } | 574 } |
| 590 | 575 |
| 591 m_client->didReceiveRedirectTo(request.url()); | 576 m_client->didReceiveRedirectTo(request.url()); |
| 592 | 577 |
| 593 // FIXME: consider combining this with CORS redirect handling performed by | 578 // FIXME: consider combining this with CORS redirect handling performed by |
| 594 // CrossOriginAccessControl::handleRedirect(). | 579 // CrossOriginAccessControl::handleRedirect(). |
| 595 clearResource(); | 580 clearResource(); |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 m_fallbackRequestForServiceWorker = ResourceRequest(); | 787 m_fallbackRequestForServiceWorker = ResourceRequest(); |
| 803 | 788 |
| 804 if (!m_sameOriginRequest && | 789 if (!m_sameOriginRequest && |
| 805 m_options.crossOriginRequestPolicy == UseAccessControl) { | 790 m_options.crossOriginRequestPolicy == UseAccessControl) { |
| 806 String accessControlErrorDescription; | 791 String accessControlErrorDescription; |
| 807 if (!passesAccessControlCheck( | 792 if (!passesAccessControlCheck( |
| 808 response, effectiveAllowCredentials(), getSecurityOrigin(), | 793 response, effectiveAllowCredentials(), getSecurityOrigin(), |
| 809 accessControlErrorDescription, m_requestContext)) { | 794 accessControlErrorDescription, m_requestContext)) { |
| 810 reportResponseReceived(identifier, response); | 795 reportResponseReceived(identifier, response); |
| 811 | 796 |
| 812 ThreadableLoaderClient* client = m_client; | 797 dispatchDidFailAccessControlCheck( |
| 813 clear(); | |
| 814 client->didFailAccessControlCheck( | |
| 815 ResourceError(errorDomainBlinkInternal, 0, response.url().getString(), | 798 ResourceError(errorDomainBlinkInternal, 0, response.url().getString(), |
| 816 accessControlErrorDescription)); | 799 accessControlErrorDescription)); |
| 817 return; | 800 return; |
| 818 } | 801 } |
| 819 } | 802 } |
| 820 | 803 |
| 821 m_client->didReceiveResponse(identifier, response, std::move(handle)); | 804 m_client->didReceiveResponse(identifier, response, std::move(handle)); |
| 822 } | 805 } |
| 823 | 806 |
| 824 void DocumentThreadableLoader::setSerializedCachedMetadata(Resource*, | 807 void DocumentThreadableLoader::setSerializedCachedMetadata(Resource*, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 861 } | 844 } |
| 862 | 845 |
| 863 void DocumentThreadableLoader::notifyFinished(Resource* resource) { | 846 void DocumentThreadableLoader::notifyFinished(Resource* resource) { |
| 864 DCHECK(m_client); | 847 DCHECK(m_client); |
| 865 DCHECK_EQ(resource, this->resource()); | 848 DCHECK_EQ(resource, this->resource()); |
| 866 DCHECK(m_async); | 849 DCHECK(m_async); |
| 867 | 850 |
| 868 m_checker.notifyFinished(resource); | 851 m_checker.notifyFinished(resource); |
| 869 | 852 |
| 870 if (resource->errorOccurred()) { | 853 if (resource->errorOccurred()) { |
| 871 handleError(resource->resourceError()); | 854 dispatchDidFail(resource->resourceError()); |
| 872 } else { | 855 } else { |
| 873 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime()); | 856 handleSuccessfulFinish(resource->identifier(), resource->loadFinishTime()); |
| 874 } | 857 } |
| 875 } | 858 } |
| 876 | 859 |
| 877 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, | 860 void DocumentThreadableLoader::handleSuccessfulFinish(unsigned long identifier, |
| 878 double finishTime) { | 861 double finishTime) { |
| 879 DCHECK(m_fallbackRequestForServiceWorker.isNull()); | 862 DCHECK(m_fallbackRequestForServiceWorker.isNull()); |
| 880 | 863 |
| 881 if (!m_actualRequest.isNull()) { | 864 if (!m_actualRequest.isNull()) { |
| 882 // FIXME: Timeout should be applied to whole fetch, not for each of | 865 // FIXME: Timeout should be applied to whole fetch, not for each of |
| 883 // preflight and actual request. | 866 // preflight and actual request. |
| 884 m_timeoutTimer.stop(); | 867 m_timeoutTimer.stop(); |
| 885 DCHECK(!m_sameOriginRequest); | 868 DCHECK(!m_sameOriginRequest); |
| 886 DCHECK_EQ(m_options.crossOriginRequestPolicy, UseAccessControl); | 869 DCHECK_EQ(m_options.crossOriginRequestPolicy, UseAccessControl); |
| 887 loadActualRequest(); | 870 loadActualRequest(); |
| 888 return; | 871 return; |
| 889 } | 872 } |
| 890 | 873 |
| 891 ThreadableLoaderClient* client = m_client; | 874 ThreadableLoaderClient* client = m_client; |
| 892 // Protect the resource in |didFinishLoading| in order not to release the | 875 // Protect the resource in |didFinishLoading| in order not to release the |
| 893 // downloaded file. | 876 // downloaded file. |
| 894 Persistent<Resource> protect = resource(); | 877 Persistent<Resource> protect = resource(); |
| 895 clear(); | 878 clear(); |
| 896 client->didFinishLoading(identifier, finishTime); | 879 client->didFinishLoading(identifier, finishTime); |
| 897 } | 880 } |
| 898 | 881 |
| 899 void DocumentThreadableLoader::didTimeout(TimerBase* timer) { | 882 void DocumentThreadableLoader::didTimeout(TimerBase* timer) { |
| 883 DCHECK(m_async); |
| 900 DCHECK_EQ(timer, &m_timeoutTimer); | 884 DCHECK_EQ(timer, &m_timeoutTimer); |
| 885 // clearResource() may be called in clear() and some other places. clear() |
| 886 // calls stop() on |m_timeoutTimer|. In the other places, the resource is set |
| 887 // again. If the creation fails, clear() is called. So, here, resource() is |
| 888 // always non-nullptr. |
| 889 DCHECK(resource()); |
| 890 // When |m_client| is set to nullptr only in clear() where |m_timeoutTimer| |
| 891 // is stopped. So, |m_client| is always non-nullptr here. |
| 892 DCHECK(m_client); |
| 901 | 893 |
| 902 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, Same as existing | 894 // Using values from net/base/net_error_list.h ERR_TIMED_OUT, Same as existing |
| 903 // FIXME above - this error should be coming from FrameLoaderClient to be | 895 // FIXME above - this error should be coming from FrameLoaderClient to be |
| 904 // identifiable. | 896 // identifiable. |
| 905 static const int timeoutError = -7; | 897 static const int timeoutError = -7; |
| 906 ResourceError error("net", timeoutError, resource()->url(), String()); | 898 ResourceError error("net", timeoutError, resource()->url(), String()); |
| 907 error.setIsTimeout(true); | 899 error.setIsTimeout(true); |
| 908 cancelWithError(error); | 900 |
| 901 dispatchDidFail(error); |
| 909 } | 902 } |
| 910 | 903 |
| 911 void DocumentThreadableLoader::loadFallbackRequestForServiceWorker() { | 904 void DocumentThreadableLoader::loadFallbackRequestForServiceWorker() { |
| 912 clearResource(); | 905 clearResource(); |
| 913 ResourceRequest fallbackRequest(m_fallbackRequestForServiceWorker); | 906 ResourceRequest fallbackRequest(m_fallbackRequestForServiceWorker); |
| 914 m_fallbackRequestForServiceWorker = ResourceRequest(); | 907 m_fallbackRequestForServiceWorker = ResourceRequest(); |
| 915 dispatchInitialRequest(fallbackRequest); | 908 dispatchInitialRequest(fallbackRequest); |
| 916 } | 909 } |
| 917 | 910 |
| 918 void DocumentThreadableLoader::loadActualRequest() { | 911 void DocumentThreadableLoader::loadActualRequest() { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 934 } | 927 } |
| 935 | 928 |
| 936 void DocumentThreadableLoader::handlePreflightFailure( | 929 void DocumentThreadableLoader::handlePreflightFailure( |
| 937 const String& url, | 930 const String& url, |
| 938 const String& errorDescription) { | 931 const String& errorDescription) { |
| 939 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); | 932 ResourceError error(errorDomainBlinkInternal, 0, url, errorDescription); |
| 940 | 933 |
| 941 // Prevent handleSuccessfulFinish() from bypassing access check. | 934 // Prevent handleSuccessfulFinish() from bypassing access check. |
| 942 m_actualRequest = ResourceRequest(); | 935 m_actualRequest = ResourceRequest(); |
| 943 | 936 |
| 937 dispatchDidFailAccessControlCheck(error); |
| 938 } |
| 939 |
| 940 void DocumentThreadableLoader::dispatchDidFailAccessControlCheck( |
| 941 const ResourceError& error) { |
| 944 ThreadableLoaderClient* client = m_client; | 942 ThreadableLoaderClient* client = m_client; |
| 945 clear(); | 943 clear(); |
| 946 client->didFailAccessControlCheck(error); | 944 client->didFailAccessControlCheck(error); |
| 947 } | 945 } |
| 948 | 946 |
| 949 void DocumentThreadableLoader::handleError(const ResourceError& error) { | 947 void DocumentThreadableLoader::dispatchDidFail(const ResourceError& error) { |
| 950 ThreadableLoaderClient* client = m_client; | 948 ThreadableLoaderClient* client = m_client; |
| 951 clear(); | 949 clear(); |
| 952 client->didFail(error); | 950 client->didFail(error); |
| 953 } | 951 } |
| 954 | 952 |
| 955 void DocumentThreadableLoader::loadRequestAsync( | 953 void DocumentThreadableLoader::loadRequestAsync( |
| 956 const ResourceRequest& request, | 954 const ResourceRequest& request, |
| 957 ResourceLoaderOptions resourceLoaderOptions) { | 955 ResourceLoaderOptions resourceLoaderOptions) { |
| 958 if (!m_actualRequest.isNull()) | 956 if (!m_actualRequest.isNull()) |
| 959 resourceLoaderOptions.dataBufferingPolicy = BufferData; | 957 resourceLoaderOptions.dataBufferingPolicy = BufferData; |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 } | 1114 } |
| 1117 | 1115 |
| 1118 DEFINE_TRACE(DocumentThreadableLoader) { | 1116 DEFINE_TRACE(DocumentThreadableLoader) { |
| 1119 visitor->trace(m_resource); | 1117 visitor->trace(m_resource); |
| 1120 visitor->trace(m_document); | 1118 visitor->trace(m_document); |
| 1121 ThreadableLoader::trace(visitor); | 1119 ThreadableLoader::trace(visitor); |
| 1122 RawResourceClient::trace(visitor); | 1120 RawResourceClient::trace(visitor); |
| 1123 } | 1121 } |
| 1124 | 1122 |
| 1125 } // namespace blink | 1123 } // namespace blink |
| OLD | NEW |