| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved. |
| 3 * (C) 2007 Graham Dennis (graham.dennis@gmail.com) | 3 * (C) 2007 Graham Dennis (graham.dennis@gmail.com) |
| 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 | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * | 8 * |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. 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 11 matching lines...) Expand all Loading... |
| 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 */ | 28 */ |
| 29 | 29 |
| 30 #include "core/fetch/ResourceLoader.h" | 30 #include "core/fetch/ResourceLoader.h" |
| 31 | 31 |
| 32 #include "core/fetch/CrossOriginAccessControl.h" |
| 33 #include "core/fetch/FetchContext.h" |
| 32 #include "core/fetch/Resource.h" | 34 #include "core/fetch/Resource.h" |
| 33 #include "core/fetch/ResourceFetcher.h" | 35 #include "core/fetch/ResourceFetcher.h" |
| 34 #include "platform/SharedBuffer.h" | 36 #include "platform/SharedBuffer.h" |
| 35 #include "platform/exported/WrappedResourceRequest.h" | 37 #include "platform/exported/WrappedResourceRequest.h" |
| 36 #include "platform/exported/WrappedResourceResponse.h" | 38 #include "platform/exported/WrappedResourceResponse.h" |
| 39 #include "platform/network/NetworkInstrumentation.h" |
| 37 #include "platform/network/ResourceError.h" | 40 #include "platform/network/ResourceError.h" |
| 38 #include "public/platform/Platform.h" | 41 #include "public/platform/Platform.h" |
| 39 #include "public/platform/WebCachePolicy.h" | 42 #include "public/platform/WebCachePolicy.h" |
| 40 #include "public/platform/WebData.h" | 43 #include "public/platform/WebData.h" |
| 41 #include "public/platform/WebURLError.h" | 44 #include "public/platform/WebURLError.h" |
| 42 #include "public/platform/WebURLRequest.h" | 45 #include "public/platform/WebURLRequest.h" |
| 43 #include "public/platform/WebURLResponse.h" | 46 #include "public/platform/WebURLResponse.h" |
| 44 #include "wtf/Assertions.h" | 47 #include "wtf/Assertions.h" |
| 45 #include "wtf/CurrentTime.h" | 48 #include "wtf/CurrentTime.h" |
| 46 #include "wtf/PtrUtil.h" | 49 #include "wtf/PtrUtil.h" |
| 47 #include <memory> | 50 #include <memory> |
| 48 | 51 |
| 49 namespace blink { | 52 namespace blink { |
| 50 | 53 |
| 51 ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher, | 54 ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher, |
| 52 Resource* resource) { | 55 Resource* resource) { |
| 53 return new ResourceLoader(fetcher, resource); | 56 return new ResourceLoader(fetcher, resource); |
| 54 } | 57 } |
| 55 | 58 |
| 56 ResourceLoader::ResourceLoader(ResourceFetcher* fetcher, Resource* resource) | 59 ResourceLoader::ResourceLoader(ResourceFetcher* fetcher, Resource* resource) |
| 57 : m_fetcher(fetcher), | 60 : m_fetcher(fetcher), |
| 58 m_resource(resource), | 61 m_resource(resource), |
| 59 m_isCacheAwareLoadingActivated(false) { | 62 m_isCacheAwareLoadingActivated(false) { |
| 60 DCHECK(m_resource); | 63 DCHECK(m_resource); |
| 61 DCHECK(m_fetcher); | 64 DCHECK(m_fetcher); |
| 65 |
| 62 m_resource->setLoader(this); | 66 m_resource->setLoader(this); |
| 63 } | 67 } |
| 64 | 68 |
| 65 ResourceLoader::~ResourceLoader() { | 69 ResourceLoader::~ResourceLoader() { |
| 66 DCHECK(!m_loader); | 70 DCHECK(!m_loader); |
| 67 } | 71 } |
| 68 | 72 |
| 69 DEFINE_TRACE(ResourceLoader) { | 73 DEFINE_TRACE(ResourceLoader) { |
| 70 visitor->trace(m_fetcher); | 74 visitor->trace(m_fetcher); |
| 71 visitor->trace(m_resource); | 75 visitor->trace(m_resource); |
| 72 } | 76 } |
| 73 | 77 |
| 74 void ResourceLoader::start(const ResourceRequest& request, | 78 void ResourceLoader::start(const ResourceRequest& request) { |
| 75 WebTaskRunner* loadingTaskRunner, | |
| 76 bool defersLoading) { | |
| 77 DCHECK(!m_loader); | 79 DCHECK(!m_loader); |
| 80 |
| 78 if (m_resource->options().synchronousPolicy == RequestSynchronously && | 81 if (m_resource->options().synchronousPolicy == RequestSynchronously && |
| 79 defersLoading) { | 82 context().defersLoading()) { |
| 80 cancel(); | 83 cancel(); |
| 81 return; | 84 return; |
| 82 } | 85 } |
| 83 | 86 |
| 84 m_loader = WTF::wrapUnique(Platform::current()->createURLLoader()); | 87 m_loader = WTF::wrapUnique(Platform::current()->createURLLoader()); |
| 85 DCHECK(m_loader); | 88 DCHECK(m_loader); |
| 86 m_loader->setDefersLoading(defersLoading); | 89 m_loader->setDefersLoading(context().defersLoading()); |
| 87 m_loader->setLoadingTaskRunner(loadingTaskRunner); | 90 m_loader->setLoadingTaskRunner(context().loadingTaskRunner()); |
| 88 | 91 |
| 89 if (m_isCacheAwareLoadingActivated) { | 92 if (m_isCacheAwareLoadingActivated) { |
| 90 // Override cache policy for cache-aware loading. If this request fails, a | 93 // Override cache policy for cache-aware loading. If this request fails, a |
| 91 // reload with original request will be triggered in didFail(). | 94 // reload with original request will be triggered in didFail(). |
| 92 ResourceRequest cacheAwareRequest(request); | 95 ResourceRequest cacheAwareRequest(request); |
| 93 cacheAwareRequest.setCachePolicy(WebCachePolicy::ReturnCacheDataIfValid); | 96 cacheAwareRequest.setCachePolicy(WebCachePolicy::ReturnCacheDataIfValid); |
| 94 m_loader->loadAsynchronously(WrappedResourceRequest(cacheAwareRequest), | 97 m_loader->loadAsynchronously(WrappedResourceRequest(cacheAwareRequest), |
| 95 this); | 98 this); |
| 96 return; | 99 return; |
| 97 } | 100 } |
| 98 | 101 |
| 99 if (m_resource->options().synchronousPolicy == RequestSynchronously) | 102 if (m_resource->options().synchronousPolicy == RequestSynchronously) |
| 100 requestSynchronously(request); | 103 requestSynchronously(request); |
| 101 else | 104 else |
| 102 m_loader->loadAsynchronously(WrappedResourceRequest(request), this); | 105 m_loader->loadAsynchronously(WrappedResourceRequest(request), this); |
| 103 } | 106 } |
| 104 | 107 |
| 105 void ResourceLoader::restart(const ResourceRequest& request, | 108 void ResourceLoader::restart(const ResourceRequest& request) { |
| 106 WebTaskRunner* loadingTaskRunner, | |
| 107 bool defersLoading) { | |
| 108 CHECK_EQ(m_resource->options().synchronousPolicy, RequestAsynchronously); | 109 CHECK_EQ(m_resource->options().synchronousPolicy, RequestAsynchronously); |
| 110 |
| 109 m_loader.reset(); | 111 m_loader.reset(); |
| 110 start(request, loadingTaskRunner, defersLoading); | 112 start(request); |
| 111 } | 113 } |
| 112 | 114 |
| 113 void ResourceLoader::setDefersLoading(bool defers) { | 115 void ResourceLoader::setDefersLoading(bool defers) { |
| 114 DCHECK(m_loader); | 116 DCHECK(m_loader); |
| 117 |
| 115 m_loader->setDefersLoading(defers); | 118 m_loader->setDefersLoading(defers); |
| 116 } | 119 } |
| 117 | 120 |
| 118 void ResourceLoader::didDownloadData(int length, int encodedDataLength) { | |
| 119 m_fetcher->didDownloadData(m_resource.get(), length, encodedDataLength); | |
| 120 m_resource->didDownloadData(length); | |
| 121 } | |
| 122 | |
| 123 void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority, | 121 void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority, |
| 124 int intraPriorityValue) { | 122 int intraPriorityValue) { |
| 125 if (m_loader) { | 123 if (m_loader) { |
| 126 m_loader->didChangePriority( | 124 m_loader->didChangePriority( |
| 127 static_cast<WebURLRequest::Priority>(loadPriority), intraPriorityValue); | 125 static_cast<WebURLRequest::Priority>(loadPriority), intraPriorityValue); |
| 128 } | 126 } |
| 129 } | 127 } |
| 130 | 128 |
| 131 void ResourceLoader::cancel() { | 129 void ResourceLoader::cancel() { |
| 132 didFail( | 130 handleError( |
| 133 ResourceError::cancelledError(m_resource->lastResourceRequest().url())); | 131 ResourceError::cancelledError(m_resource->lastResourceRequest().url())); |
| 134 } | 132 } |
| 135 | 133 |
| 136 void ResourceLoader::cancelForRedirectAccessCheckError( | 134 void ResourceLoader::cancelForRedirectAccessCheckError( |
| 137 const KURL& newURL, | 135 const KURL& newURL, |
| 138 ResourceRequestBlockedReason blockedReason) { | 136 ResourceRequestBlockedReason blockedReason) { |
| 139 m_resource->willNotFollowRedirect(); | 137 m_resource->willNotFollowRedirect(); |
| 140 | 138 |
| 141 if (m_loader) { | 139 if (m_loader) |
| 142 didFail( | 140 handleError( |
| 143 ResourceError::cancelledDueToAccessCheckError(newURL, blockedReason)); | 141 ResourceError::cancelledDueToAccessCheckError(newURL, blockedReason)); |
| 144 } | 142 } |
| 143 |
| 144 static bool isManualRedirectFetchRequest(const ResourceRequest& request) { |
| 145 return request.fetchRedirectMode() == |
| 146 WebURLRequest::FetchRedirectModeManual && |
| 147 request.requestContext() == WebURLRequest::RequestContextFetch; |
| 145 } | 148 } |
| 146 | 149 |
| 147 bool ResourceLoader::willFollowRedirect( | 150 bool ResourceLoader::willFollowRedirect( |
| 148 WebURLRequest& passedNewRequest, | 151 WebURLRequest& passedNewRequest, |
| 149 const WebURLResponse& passedRedirectResponse) { | 152 const WebURLResponse& passedRedirectResponse) { |
| 150 DCHECK(!passedNewRequest.isNull()); | 153 DCHECK(!passedNewRequest.isNull()); |
| 151 DCHECK(!passedRedirectResponse.isNull()); | 154 DCHECK(!passedRedirectResponse.isNull()); |
| 152 | 155 |
| 153 if (m_isCacheAwareLoadingActivated) { | 156 if (m_isCacheAwareLoadingActivated) { |
| 154 // Fail as cache miss if cached response is a redirect. | 157 // Fail as cache miss if cached response is a redirect. |
| 155 didFail( | 158 handleError( |
| 156 ResourceError::cacheMissError(m_resource->lastResourceRequest().url())); | 159 ResourceError::cacheMissError(m_resource->lastResourceRequest().url())); |
| 157 return false; | 160 return false; |
| 158 } | 161 } |
| 159 | 162 |
| 160 ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest()); | 163 ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest()); |
| 161 const ResourceResponse& redirectResponse( | 164 const ResourceResponse& redirectResponse( |
| 162 passedRedirectResponse.toResourceResponse()); | 165 passedRedirectResponse.toResourceResponse()); |
| 166 |
| 163 newRequest.setRedirectStatus( | 167 newRequest.setRedirectStatus( |
| 164 ResourceRequest::RedirectStatus::FollowedRedirect); | 168 ResourceRequest::RedirectStatus::FollowedRedirect); |
| 165 | 169 |
| 166 const KURL originalURL = newRequest.url(); | 170 const KURL originalURL = newRequest.url(); |
| 167 | 171 |
| 168 ResourceRequestBlockedReason blockedReason = m_fetcher->willFollowRedirect( | 172 if (!isManualRedirectFetchRequest(m_resource->resourceRequest())) { |
| 169 m_resource.get(), newRequest, redirectResponse); | 173 ResourceRequestBlockedReason blockedReason = context().canRequest( |
| 170 if (blockedReason != ResourceRequestBlockedReason::None) { | 174 m_resource->getType(), newRequest, newRequest.url(), |
| 171 cancelForRedirectAccessCheckError(newRequest.url(), blockedReason); | 175 m_resource->options(), m_resource->isUnusedPreload(), |
| 172 return false; | 176 FetchRequest::UseDefaultOriginRestrictionForType); |
| 177 if (blockedReason != ResourceRequestBlockedReason::None) { |
| 178 cancelForRedirectAccessCheckError(newRequest.url(), blockedReason); |
| 179 return false; |
| 180 } |
| 181 |
| 182 if (m_resource->options().corsEnabled == IsCORSEnabled) { |
| 183 RefPtr<SecurityOrigin> sourceOrigin = |
| 184 m_resource->options().securityOrigin; |
| 185 if (!sourceOrigin.get()) |
| 186 sourceOrigin = context().getSecurityOrigin(); |
| 187 |
| 188 String errorMessage; |
| 189 StoredCredentials withCredentials = |
| 190 m_resource->lastResourceRequest().allowStoredCredentials() |
| 191 ? AllowStoredCredentials |
| 192 : DoNotAllowStoredCredentials; |
| 193 if (!CrossOriginAccessControl::handleRedirect( |
| 194 sourceOrigin, newRequest, redirectResponse, withCredentials, |
| 195 m_resource->mutableOptions(), errorMessage)) { |
| 196 m_resource->setCORSFailed(); |
| 197 context().addConsoleMessage(errorMessage); |
| 198 cancelForRedirectAccessCheckError(newRequest.url(), |
| 199 ResourceRequestBlockedReason::Other); |
| 200 return false; |
| 201 } |
| 202 } |
| 203 if (m_resource->getType() == Resource::Image && |
| 204 m_fetcher->shouldDeferImageLoad(newRequest.url())) { |
| 205 cancelForRedirectAccessCheckError(newRequest.url(), |
| 206 ResourceRequestBlockedReason::Other); |
| 207 return false; |
| 208 } |
| 173 } | 209 } |
| 174 | 210 |
| 211 bool crossOrigin = !SecurityOrigin::areSameSchemeHostPort( |
| 212 redirectResponse.url(), newRequest.url()); |
| 213 m_fetcher->recordResourceTimingOnRedirect(m_resource.get(), redirectResponse, |
| 214 crossOrigin); |
| 215 |
| 216 newRequest.setAllowStoredCredentials(m_resource->options().allowCredentials == |
| 217 AllowStoredCredentials); |
| 218 |
| 219 context().dispatchWillSendRequest(m_resource->identifier(), newRequest, |
| 220 redirectResponse, |
| 221 m_resource->options().initiatorInfo); |
| 222 |
| 175 // ResourceFetcher::willFollowRedirect() may rewrite the URL to | 223 // ResourceFetcher::willFollowRedirect() may rewrite the URL to |
| 176 // something else not for rejecting redirect but for other reasons. | 224 // something else not for rejecting redirect but for other reasons. |
| 177 // E.g. WebFrameTestClient::willSendRequest() and | 225 // E.g. WebFrameTestClient::willSendRequest() and |
| 178 // RenderFrameImpl::willSendRequest(). We should reflect the | 226 // RenderFrameImpl::willSendRequest(). We should reflect the |
| 179 // rewriting but currently we cannot. So, return false to make the | 227 // rewriting but currently we cannot. So, return false to make the |
| 180 // redirect fail. | 228 // redirect fail. |
| 181 if (newRequest.url() != originalURL) { | 229 if (newRequest.url() != originalURL) { |
| 182 cancelForRedirectAccessCheckError(newRequest.url(), | 230 cancelForRedirectAccessCheckError(newRequest.url(), |
| 183 ResourceRequestBlockedReason::Other); | 231 ResourceRequestBlockedReason::Other); |
| 184 return false; | 232 return false; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 195 | 243 |
| 196 void ResourceLoader::didReceiveCachedMetadata(const char* data, int length) { | 244 void ResourceLoader::didReceiveCachedMetadata(const char* data, int length) { |
| 197 m_resource->setSerializedCachedMetadata(data, length); | 245 m_resource->setSerializedCachedMetadata(data, length); |
| 198 } | 246 } |
| 199 | 247 |
| 200 void ResourceLoader::didSendData(unsigned long long bytesSent, | 248 void ResourceLoader::didSendData(unsigned long long bytesSent, |
| 201 unsigned long long totalBytesToBeSent) { | 249 unsigned long long totalBytesToBeSent) { |
| 202 m_resource->didSendData(bytesSent, totalBytesToBeSent); | 250 m_resource->didSendData(bytesSent, totalBytesToBeSent); |
| 203 } | 251 } |
| 204 | 252 |
| 253 FetchContext& ResourceLoader::context() const { |
| 254 return m_fetcher->context(); |
| 255 } |
| 256 |
| 257 ResourceRequestBlockedReason ResourceLoader::canAccessResponse( |
| 258 Resource* resource, |
| 259 const ResourceResponse& response) const { |
| 260 // Redirects can change the response URL different from one of request. |
| 261 bool forPreload = resource->isUnusedPreload(); |
| 262 ResourceRequestBlockedReason blockedReason = |
| 263 context().canRequest(resource->getType(), resource->resourceRequest(), |
| 264 response.url(), resource->options(), forPreload, |
| 265 FetchRequest::UseDefaultOriginRestrictionForType); |
| 266 if (blockedReason != ResourceRequestBlockedReason::None) |
| 267 return blockedReason; |
| 268 |
| 269 SecurityOrigin* sourceOrigin = resource->options().securityOrigin.get(); |
| 270 if (!sourceOrigin) |
| 271 sourceOrigin = context().getSecurityOrigin(); |
| 272 |
| 273 if (sourceOrigin->canRequestNoSuborigin(response.url())) |
| 274 return ResourceRequestBlockedReason::None; |
| 275 |
| 276 // Use the original response instead of the 304 response for a successful |
| 277 // revaldiation. |
| 278 const ResourceResponse& responseForAccessControl = |
| 279 (resource->isCacheValidator() && response.httpStatusCode() == 304) |
| 280 ? resource->response() |
| 281 : response; |
| 282 String errorDescription; |
| 283 if (!passesAccessControlCheck( |
| 284 responseForAccessControl, resource->options().allowCredentials, |
| 285 sourceOrigin, errorDescription, |
| 286 resource->lastResourceRequest().requestContext())) { |
| 287 resource->setCORSFailed(); |
| 288 if (!forPreload) { |
| 289 String resourceType = Resource::resourceTypeToString( |
| 290 resource->getType(), resource->options().initiatorInfo); |
| 291 context().addConsoleMessage( |
| 292 "Access to " + resourceType + " at '" + response.url().getString() + |
| 293 "' from origin '" + sourceOrigin->toString() + |
| 294 "' has been blocked by CORS policy: " + errorDescription); |
| 295 } |
| 296 return ResourceRequestBlockedReason::Other; |
| 297 } |
| 298 return ResourceRequestBlockedReason::None; |
| 299 } |
| 300 |
| 205 void ResourceLoader::didReceiveResponse( | 301 void ResourceLoader::didReceiveResponse( |
| 206 const WebURLResponse& response, | 302 const WebURLResponse& webURLResponse, |
| 207 std::unique_ptr<WebDataConsumerHandle> handle) { | 303 std::unique_ptr<WebDataConsumerHandle> handle) { |
| 208 DCHECK(!response.isNull()); | 304 DCHECK(!webURLResponse.isNull()); |
| 209 m_fetcher->didReceiveResponse(m_resource.get(), response.toResourceResponse(), | 305 |
| 210 std::move(handle)); | 306 const ResourceResponse& response = webURLResponse.toResourceResponse(); |
| 307 |
| 308 if (response.wasFetchedViaServiceWorker()) { |
| 309 if (m_resource->options().corsEnabled == IsCORSEnabled && |
| 310 response.wasFallbackRequiredByServiceWorker()) { |
| 311 ResourceRequest request = m_resource->lastResourceRequest(); |
| 312 DCHECK_EQ(request.skipServiceWorker(), |
| 313 WebURLRequest::SkipServiceWorker::None); |
| 314 // This code handles the case when a regular controlling service worker |
| 315 // doesn't handle a cross origin request. When this happens we still want |
| 316 // to give foreign fetch a chance to handle the request, so only skip the |
| 317 // controlling service worker for the fallback request. This is currently |
| 318 // safe because of http://crbug.com/604084 the |
| 319 // wasFallbackRequiredByServiceWorker flag is never set when foreign fetch |
| 320 // handled a request. |
| 321 if (!context().shouldLoadNewResource(m_resource->getType())) { |
| 322 // Cancel the request if we should not trigger a reload now. |
| 323 handleError(ResourceError::cancelledError(response.url())); |
| 324 return; |
| 325 } |
| 326 request.setSkipServiceWorker( |
| 327 WebURLRequest::SkipServiceWorker::Controlling); |
| 328 restart(request); |
| 329 return; |
| 330 } |
| 331 |
| 332 // If the response is fetched via ServiceWorker, the original URL of the |
| 333 // response could be different from the URL of the request. We check the URL |
| 334 // not to load the resources which are forbidden by the page CSP. |
| 335 // https://w3c.github.io/webappsec-csp/#should-block-response |
| 336 const KURL& originalURL = response.originalURLViaServiceWorker(); |
| 337 if (!originalURL.isEmpty()) { |
| 338 ResourceRequestBlockedReason blockedReason = context().allowResponse( |
| 339 m_resource->getType(), m_resource->resourceRequest(), originalURL, |
| 340 m_resource->options()); |
| 341 if (blockedReason != ResourceRequestBlockedReason::None) { |
| 342 handleError(ResourceError::cancelledDueToAccessCheckError( |
| 343 originalURL, blockedReason)); |
| 344 return; |
| 345 } |
| 346 } |
| 347 } else if (m_resource->options().corsEnabled == IsCORSEnabled) { |
| 348 ResourceRequestBlockedReason blockedReason = |
| 349 canAccessResponse(m_resource, response); |
| 350 if (blockedReason != ResourceRequestBlockedReason::None) { |
| 351 handleError(ResourceError::cancelledDueToAccessCheckError(response.url(), |
| 352 blockedReason)); |
| 353 return; |
| 354 } |
| 355 } |
| 356 |
| 357 context().dispatchDidReceiveResponse( |
| 358 m_resource->identifier(), response, |
| 359 m_resource->resourceRequest().frameType(), |
| 360 m_resource->resourceRequest().requestContext(), m_resource); |
| 361 |
| 362 m_resource->responseReceived(response, std::move(handle)); |
| 363 if (!m_resource->loader()) |
| 364 return; |
| 365 |
| 366 if (response.httpStatusCode() >= 400 && |
| 367 !m_resource->shouldIgnoreHTTPStatusCodeErrors()) |
| 368 handleError(ResourceError::cancelledError(response.url())); |
| 211 } | 369 } |
| 212 | 370 |
| 213 void ResourceLoader::didReceiveResponse(const WebURLResponse& response) { | 371 void ResourceLoader::didReceiveResponse(const WebURLResponse& response) { |
| 214 didReceiveResponse(response, nullptr); | 372 didReceiveResponse(response, nullptr); |
| 215 } | 373 } |
| 216 | 374 |
| 375 void ResourceLoader::didDownloadData(int length, int encodedDataLength) { |
| 376 context().dispatchDidDownloadData(m_resource->identifier(), length, |
| 377 encodedDataLength); |
| 378 m_resource->didDownloadData(length); |
| 379 } |
| 380 |
| 217 void ResourceLoader::didReceiveData(const char* data, int length) { | 381 void ResourceLoader::didReceiveData(const char* data, int length) { |
| 218 CHECK_GE(length, 0); | 382 CHECK_GE(length, 0); |
| 219 m_fetcher->didReceiveData(m_resource.get(), data, length); | 383 |
| 384 context().dispatchDidReceiveData(m_resource->identifier(), data, length); |
| 220 m_resource->addToDecodedBodyLength(length); | 385 m_resource->addToDecodedBodyLength(length); |
| 221 m_resource->appendData(data, length); | 386 m_resource->appendData(data, length); |
| 222 } | 387 } |
| 223 | 388 |
| 224 void ResourceLoader::didReceiveTransferSizeUpdate(int transferSizeDiff) { | 389 void ResourceLoader::didReceiveTransferSizeUpdate(int transferSizeDiff) { |
| 225 DCHECK_GT(transferSizeDiff, 0); | 390 DCHECK_GT(transferSizeDiff, 0); |
| 226 m_fetcher->didReceiveTransferSizeUpdate(m_resource.get(), transferSizeDiff); | 391 context().dispatchDidReceiveEncodedData(m_resource->identifier(), |
| 392 transferSizeDiff); |
| 227 } | 393 } |
| 228 | 394 |
| 229 void ResourceLoader::didFinishLoadingFirstPartInMultipart() { | 395 void ResourceLoader::didFinishLoadingFirstPartInMultipart() { |
| 230 m_fetcher->didFinishLoading(m_resource.get(), 0, | 396 network_instrumentation::endResourceLoad( |
| 231 ResourceFetcher::DidFinishFirstPartInMultipart); | 397 m_resource->identifier(), |
| 398 network_instrumentation::RequestOutcome::Success); |
| 399 |
| 400 m_fetcher->handleLoaderFinish(m_resource.get(), 0, |
| 401 ResourceFetcher::DidFinishFirstPartInMultipart); |
| 232 } | 402 } |
| 233 | 403 |
| 234 void ResourceLoader::didFinishLoading(double finishTime, | 404 void ResourceLoader::didFinishLoading(double finishTime, |
| 235 int64_t encodedDataLength, | 405 int64_t encodedDataLength, |
| 236 int64_t encodedBodyLength) { | 406 int64_t encodedBodyLength) { |
| 237 m_resource->setEncodedDataLength(encodedDataLength); | 407 m_resource->setEncodedDataLength(encodedDataLength); |
| 238 m_resource->addToEncodedBodyLength(encodedBodyLength); | 408 m_resource->addToEncodedBodyLength(encodedBodyLength); |
| 409 |
| 239 m_loader.reset(); | 410 m_loader.reset(); |
| 240 m_fetcher->didFinishLoading(m_resource.get(), finishTime, | 411 |
| 241 ResourceFetcher::DidFinishLoading); | 412 network_instrumentation::endResourceLoad( |
| 413 m_resource->identifier(), |
| 414 network_instrumentation::RequestOutcome::Success); |
| 415 |
| 416 m_fetcher->handleLoaderFinish(m_resource.get(), finishTime, |
| 417 ResourceFetcher::DidFinishLoading); |
| 242 } | 418 } |
| 243 | 419 |
| 244 void ResourceLoader::didFail(const WebURLError& error, | 420 void ResourceLoader::didFail(const WebURLError& error, |
| 245 int64_t encodedDataLength, | 421 int64_t encodedDataLength, |
| 246 int64_t encodedBodyLength) { | 422 int64_t encodedBodyLength) { |
| 247 m_resource->setEncodedDataLength(encodedDataLength); | 423 m_resource->setEncodedDataLength(encodedDataLength); |
| 248 m_resource->addToEncodedBodyLength(encodedBodyLength); | 424 m_resource->addToEncodedBodyLength(encodedBodyLength); |
| 249 didFail(error); | 425 handleError(error); |
| 250 } | 426 } |
| 251 | 427 |
| 252 void ResourceLoader::didFail(const ResourceError& error) { | 428 void ResourceLoader::handleError(const ResourceError& error) { |
| 253 if (m_isCacheAwareLoadingActivated && error.isCacheMiss() && | 429 if (m_isCacheAwareLoadingActivated && error.isCacheMiss() && |
| 254 m_fetcher->context().shouldLoadNewResource(m_resource->getType())) { | 430 context().shouldLoadNewResource(m_resource->getType())) { |
| 255 m_resource->willReloadAfterDiskCacheMiss(); | 431 m_resource->willReloadAfterDiskCacheMiss(); |
| 256 m_isCacheAwareLoadingActivated = false; | 432 m_isCacheAwareLoadingActivated = false; |
| 257 restart(m_resource->resourceRequest(), | 433 restart(m_resource->resourceRequest()); |
| 258 m_fetcher->context().loadingTaskRunner(), | |
| 259 m_fetcher->context().defersLoading()); | |
| 260 return; | 434 return; |
| 261 } | 435 } |
| 262 | 436 |
| 263 m_loader.reset(); | 437 m_loader.reset(); |
| 264 m_fetcher->didFailLoading(m_resource.get(), error); | 438 |
| 439 network_instrumentation::endResourceLoad( |
| 440 m_resource->identifier(), network_instrumentation::RequestOutcome::Fail); |
| 441 |
| 442 m_fetcher->handleLoaderError(m_resource.get(), error); |
| 265 } | 443 } |
| 266 | 444 |
| 267 void ResourceLoader::requestSynchronously(const ResourceRequest& request) { | 445 void ResourceLoader::requestSynchronously(const ResourceRequest& request) { |
| 268 // downloadToFile is not supported for synchronous requests. | 446 // downloadToFile is not supported for synchronous requests. |
| 269 DCHECK(!request.downloadToFile()); | 447 DCHECK(!request.downloadToFile()); |
| 270 DCHECK(m_loader); | 448 DCHECK(m_loader); |
| 271 DCHECK_EQ(request.priority(), ResourceLoadPriorityHighest); | 449 DCHECK_EQ(request.priority(), ResourceLoadPriorityHighest); |
| 272 | 450 |
| 273 WrappedResourceRequest requestIn(request); | 451 WrappedResourceRequest requestIn(request); |
| 274 WebURLResponse responseOut; | 452 WebURLResponse responseOut; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 290 didReceiveResponse(responseOut); | 468 didReceiveResponse(responseOut); |
| 291 if (!m_loader) | 469 if (!m_loader) |
| 292 return; | 470 return; |
| 293 DCHECK_GE(responseOut.toResourceResponse().encodedBodyLength(), 0); | 471 DCHECK_GE(responseOut.toResourceResponse().encodedBodyLength(), 0); |
| 294 | 472 |
| 295 // Follow the async case convention of not calling didReceiveData or | 473 // Follow the async case convention of not calling didReceiveData or |
| 296 // appending data to m_resource if the response body is empty. Copying the | 474 // appending data to m_resource if the response body is empty. Copying the |
| 297 // empty buffer is a noop in most cases, but is destructive in the case of | 475 // empty buffer is a noop in most cases, but is destructive in the case of |
| 298 // a 304, where it will overwrite the cached data we should be reusing. | 476 // a 304, where it will overwrite the cached data we should be reusing. |
| 299 if (dataOut.size()) { | 477 if (dataOut.size()) { |
| 300 m_fetcher->didReceiveData(m_resource.get(), dataOut.data(), dataOut.size()); | 478 context().dispatchDidReceiveData(m_resource->identifier(), dataOut.data(), |
| 479 dataOut.size()); |
| 301 m_resource->setResourceBuffer(dataOut); | 480 m_resource->setResourceBuffer(dataOut); |
| 302 } | 481 } |
| 303 didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength, | 482 didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength, |
| 304 encodedBodyLength); | 483 encodedBodyLength); |
| 305 } | 484 } |
| 306 | 485 |
| 307 void ResourceLoader::activateCacheAwareLoadingIfNeeded( | 486 void ResourceLoader::activateCacheAwareLoadingIfNeeded( |
| 308 const ResourceRequest& request) { | 487 const ResourceRequest& request) { |
| 309 DCHECK(!m_isCacheAwareLoadingActivated); | 488 DCHECK(!m_isCacheAwareLoadingActivated); |
| 310 | 489 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 321 return; | 500 return; |
| 322 | 501 |
| 323 // Don't activate if cache policy is explicitly set. | 502 // Don't activate if cache policy is explicitly set. |
| 324 if (request.getCachePolicy() != WebCachePolicy::UseProtocolCachePolicy) | 503 if (request.getCachePolicy() != WebCachePolicy::UseProtocolCachePolicy) |
| 325 return; | 504 return; |
| 326 | 505 |
| 327 m_isCacheAwareLoadingActivated = true; | 506 m_isCacheAwareLoadingActivated = true; |
| 328 } | 507 } |
| 329 | 508 |
| 330 } // namespace blink | 509 } // namespace blink |
| OLD | NEW |