| OLD | NEW |
| 1 /* | 1 /* |
| 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) | 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) |
| 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) | 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) |
| 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) | 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) |
| 5 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All | 5 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All |
| 6 rights reserved. | 6 rights reserved. |
| 7 Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ | 7 Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ |
| 8 | 8 |
| 9 This library is free software; you can redistribute it and/or | 9 This library is free software; you can redistribute it and/or |
| 10 modify it under the terms of the GNU Library General Public | 10 modify it under the terms of the GNU Library General Public |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 } | 251 } |
| 252 | 252 |
| 253 ResourceFetcher::~ResourceFetcher() {} | 253 ResourceFetcher::~ResourceFetcher() {} |
| 254 | 254 |
| 255 Resource* ResourceFetcher::cachedResource(const KURL& resourceURL) const { | 255 Resource* ResourceFetcher::cachedResource(const KURL& resourceURL) const { |
| 256 KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL); | 256 KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL); |
| 257 const WeakMember<Resource>& resource = m_documentResources.get(url); | 257 const WeakMember<Resource>& resource = m_documentResources.get(url); |
| 258 return resource.get(); | 258 return resource.get(); |
| 259 } | 259 } |
| 260 | 260 |
| 261 bool ResourceFetcher::canAccessResponse( | 261 ResourceRequestBlockedReason ResourceFetcher::canAccessResponse( |
| 262 Resource* resource, | 262 Resource* resource, |
| 263 const ResourceResponse& response) const { | 263 const ResourceResponse& response) const { |
| 264 // Redirects can change the response URL different from one of request. | 264 // Redirects can change the response URL different from one of request. |
| 265 bool forPreload = resource->isUnusedPreload(); | 265 bool forPreload = resource->isUnusedPreload(); |
| 266 if (!context().canRequest(resource->getType(), resource->resourceRequest(), | 266 ResourceRequestBlockedReason blockedReason = |
| 267 response.url(), resource->options(), forPreload, | 267 context().canRequest(resource->getType(), resource->resourceRequest(), |
| 268 FetchRequest::UseDefaultOriginRestrictionForType)) | 268 response.url(), resource->options(), forPreload, |
| 269 return false; | 269 FetchRequest::UseDefaultOriginRestrictionForType); |
| 270 if (blockedReason != ResourceRequestBlockedReason::None) |
| 271 return blockedReason; |
| 270 | 272 |
| 271 SecurityOrigin* sourceOrigin = resource->options().securityOrigin.get(); | 273 SecurityOrigin* sourceOrigin = resource->options().securityOrigin.get(); |
| 272 if (!sourceOrigin) | 274 if (!sourceOrigin) |
| 273 sourceOrigin = context().getSecurityOrigin(); | 275 sourceOrigin = context().getSecurityOrigin(); |
| 274 | 276 |
| 275 if (sourceOrigin->canRequestNoSuborigin(response.url())) | 277 if (sourceOrigin->canRequestNoSuborigin(response.url())) |
| 276 return true; | 278 return ResourceRequestBlockedReason::None; |
| 277 | 279 |
| 278 // Use the original response instead of the 304 response for a successful | 280 // Use the original response instead of the 304 response for a successful |
| 279 // revaldiation. | 281 // revaldiation. |
| 280 const ResourceResponse& responseForAccessControl = | 282 const ResourceResponse& responseForAccessControl = |
| 281 (resource->isCacheValidator() && response.httpStatusCode() == 304) | 283 (resource->isCacheValidator() && response.httpStatusCode() == 304) |
| 282 ? resource->response() | 284 ? resource->response() |
| 283 : response; | 285 : response; |
| 284 String errorDescription; | 286 String errorDescription; |
| 285 if (!passesAccessControlCheck( | 287 if (!passesAccessControlCheck( |
| 286 responseForAccessControl, resource->options().allowCredentials, | 288 responseForAccessControl, resource->options().allowCredentials, |
| 287 sourceOrigin, errorDescription, | 289 sourceOrigin, errorDescription, |
| 288 resource->lastResourceRequest().requestContext())) { | 290 resource->lastResourceRequest().requestContext())) { |
| 289 resource->setCORSFailed(); | 291 resource->setCORSFailed(); |
| 290 if (!forPreload) { | 292 if (!forPreload) { |
| 291 String resourceType = Resource::resourceTypeToString( | 293 String resourceType = Resource::resourceTypeToString( |
| 292 resource->getType(), resource->options().initiatorInfo); | 294 resource->getType(), resource->options().initiatorInfo); |
| 293 context().addConsoleMessage( | 295 context().addConsoleMessage( |
| 294 "Access to " + resourceType + " at '" + response.url().getString() + | 296 "Access to " + resourceType + " at '" + response.url().getString() + |
| 295 "' from origin '" + sourceOrigin->toString() + | 297 "' from origin '" + sourceOrigin->toString() + |
| 296 "' has been blocked by CORS policy: " + errorDescription); | 298 "' has been blocked by CORS policy: " + errorDescription); |
| 297 } | 299 } |
| 298 return false; | 300 return ResourceRequestBlockedReason::Other; |
| 299 } | 301 } |
| 300 return true; | 302 return ResourceRequestBlockedReason::None; |
| 301 } | 303 } |
| 302 | 304 |
| 303 bool ResourceFetcher::isControlledByServiceWorker() const { | 305 bool ResourceFetcher::isControlledByServiceWorker() const { |
| 304 return context().isControlledByServiceWorker(); | 306 return context().isControlledByServiceWorker(); |
| 305 } | 307 } |
| 306 | 308 |
| 307 bool ResourceFetcher::resourceNeedsLoad(Resource* resource, | 309 bool ResourceFetcher::resourceNeedsLoad(Resource* resource, |
| 308 const FetchRequest& request, | 310 const FetchRequest& request, |
| 309 RevalidationPolicy policy) { | 311 RevalidationPolicy policy) { |
| 310 // Defer a font load until it is actually needed unless this is a preload. | 312 // Defer a font load until it is actually needed unless this is a preload. |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 resource->finish(); | 432 resource->finish(); |
| 431 | 433 |
| 432 if (!substituteData.isValid()) | 434 if (!substituteData.isValid()) |
| 433 memoryCache()->add(resource); | 435 memoryCache()->add(resource); |
| 434 | 436 |
| 435 return resource; | 437 return resource; |
| 436 } | 438 } |
| 437 | 439 |
| 438 Resource* ResourceFetcher::resourceForBlockedRequest( | 440 Resource* ResourceFetcher::resourceForBlockedRequest( |
| 439 const FetchRequest& request, | 441 const FetchRequest& request, |
| 440 const ResourceFactory& factory) { | 442 const ResourceFactory& factory, |
| 443 ResourceRequestBlockedReason blockedReason) { |
| 441 Resource* resource = factory.create(request.resourceRequest(), | 444 Resource* resource = factory.create(request.resourceRequest(), |
| 442 request.options(), request.charset()); | 445 request.options(), request.charset()); |
| 443 resource->error(ResourceError::cancelledDueToAccessCheckError(request.url())); | 446 resource->error(ResourceError::cancelledDueToAccessCheckError(request.url(), |
| 447 blockedReason)); |
| 444 return resource; | 448 return resource; |
| 445 } | 449 } |
| 446 | 450 |
| 447 void ResourceFetcher::moveCachedNonBlockingResourceToBlocking( | 451 void ResourceFetcher::moveCachedNonBlockingResourceToBlocking( |
| 448 Resource* resource, | 452 Resource* resource, |
| 449 const FetchRequest& request) { | 453 const FetchRequest& request) { |
| 450 // TODO(yoav): Test that non-blocking resources (video/audio/track) continue | 454 // TODO(yoav): Test that non-blocking resources (video/audio/track) continue |
| 451 // to not-block even after being preloaded and discovered. | 455 // to not-block even after being preloaded and discovered. |
| 452 if (resource && resource->loader() && | 456 if (resource && resource->loader() && |
| 453 resource->isLoadEventBlockingResourceType() && | 457 resource->isLoadEventBlockingResourceType() && |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 if (!request.url().isValid()) | 510 if (!request.url().isValid()) |
| 507 return nullptr; | 511 return nullptr; |
| 508 | 512 |
| 509 request.mutableResourceRequest().setPriority(computeLoadPriority( | 513 request.mutableResourceRequest().setPriority(computeLoadPriority( |
| 510 factory.type(), request, ResourcePriority::NotVisible)); | 514 factory.type(), request, ResourcePriority::NotVisible)); |
| 511 initializeResourceRequest(request.mutableResourceRequest(), factory.type(), | 515 initializeResourceRequest(request.mutableResourceRequest(), factory.type(), |
| 512 request.defer()); | 516 request.defer()); |
| 513 network_instrumentation::resourcePrioritySet( | 517 network_instrumentation::resourcePrioritySet( |
| 514 identifier, request.resourceRequest().priority()); | 518 identifier, request.resourceRequest().priority()); |
| 515 | 519 |
| 516 if (!context().canRequest( | 520 ResourceRequestBlockedReason blockedReason = context().canRequest( |
| 517 factory.type(), request.resourceRequest(), | 521 factory.type(), request.resourceRequest(), |
| 518 MemoryCache::removeFragmentIdentifierIfNeeded(request.url()), | 522 MemoryCache::removeFragmentIdentifierIfNeeded(request.url()), |
| 519 request.options(), request.forPreload(), | 523 request.options(), request.forPreload(), request.getOriginRestriction()); |
| 520 request.getOriginRestriction())) { | 524 if (blockedReason != ResourceRequestBlockedReason::None) { |
| 521 DCHECK(!substituteData.forceSynchronousLoad()); | 525 DCHECK(!substituteData.forceSynchronousLoad()); |
| 522 return resourceForBlockedRequest(request, factory); | 526 return resourceForBlockedRequest(request, factory, blockedReason); |
| 523 } | 527 } |
| 524 | 528 |
| 525 context().willStartLoadingResource( | 529 context().willStartLoadingResource( |
| 526 identifier, request.mutableResourceRequest(), factory.type()); | 530 identifier, request.mutableResourceRequest(), factory.type()); |
| 527 if (!request.url().isValid()) | 531 if (!request.url().isValid()) |
| 528 return nullptr; | 532 return nullptr; |
| 529 | 533 |
| 530 if (!request.forPreload()) { | 534 if (!request.forPreload()) { |
| 531 V8DOMActivityLogger* activityLogger = nullptr; | 535 V8DOMActivityLogger* activityLogger = nullptr; |
| 532 if (request.options().initiatorInfo.name == | 536 if (request.options().initiatorInfo.name == |
| (...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1225 resource->loader()->restart(request, context().loadingTaskRunner(), | 1229 resource->loader()->restart(request, context().loadingTaskRunner(), |
| 1226 context().defersLoading()); | 1230 context().defersLoading()); |
| 1227 return; | 1231 return; |
| 1228 } | 1232 } |
| 1229 | 1233 |
| 1230 // If the response is fetched via ServiceWorker, the original URL of the | 1234 // If the response is fetched via ServiceWorker, the original URL of the |
| 1231 // response could be different from the URL of the request. We check the URL | 1235 // response could be different from the URL of the request. We check the URL |
| 1232 // not to load the resources which are forbidden by the page CSP. | 1236 // not to load the resources which are forbidden by the page CSP. |
| 1233 // https://w3c.github.io/webappsec-csp/#should-block-response | 1237 // https://w3c.github.io/webappsec-csp/#should-block-response |
| 1234 const KURL& originalURL = response.originalURLViaServiceWorker(); | 1238 const KURL& originalURL = response.originalURLViaServiceWorker(); |
| 1235 if (!originalURL.isEmpty() && | 1239 if (!originalURL.isEmpty()) { |
| 1236 !context().allowResponse(resource->getType(), | 1240 ResourceRequestBlockedReason blockedReason = context().allowResponse( |
| 1237 resource->resourceRequest(), originalURL, | 1241 resource->getType(), resource->resourceRequest(), originalURL, |
| 1238 resource->options())) { | 1242 resource->options()); |
| 1239 resource->loader()->didFail( | 1243 if (blockedReason != ResourceRequestBlockedReason::None) { |
| 1240 ResourceError::cancelledDueToAccessCheckError(originalURL)); | 1244 resource->loader()->didFail( |
| 1245 ResourceError::cancelledDueToAccessCheckError(originalURL, |
| 1246 blockedReason)); |
| 1247 return; |
| 1248 } |
| 1249 } |
| 1250 } else if (resource->options().corsEnabled == IsCORSEnabled) { |
| 1251 ResourceRequestBlockedReason blockedReason = |
| 1252 canAccessResponse(resource, response); |
| 1253 if (blockedReason != ResourceRequestBlockedReason::None) { |
| 1254 resource->loader()->didFail(ResourceError::cancelledDueToAccessCheckError( |
| 1255 response.url(), blockedReason)); |
| 1241 return; | 1256 return; |
| 1242 } | 1257 } |
| 1243 } else if (resource->options().corsEnabled == IsCORSEnabled && | |
| 1244 !canAccessResponse(resource, response)) { | |
| 1245 resource->loader()->didFail( | |
| 1246 ResourceError::cancelledDueToAccessCheckError(response.url())); | |
| 1247 return; | |
| 1248 } | 1258 } |
| 1249 | 1259 |
| 1250 context().dispatchDidReceiveResponse( | 1260 context().dispatchDidReceiveResponse( |
| 1251 resource->identifier(), response, resource->resourceRequest().frameType(), | 1261 resource->identifier(), response, resource->resourceRequest().frameType(), |
| 1252 resource->resourceRequest().requestContext(), resource); | 1262 resource->resourceRequest().requestContext(), resource); |
| 1253 resource->responseReceived(response, std::move(handle)); | 1263 resource->responseReceived(response, std::move(handle)); |
| 1254 if (resource->loader() && response.httpStatusCode() >= 400 && | 1264 if (resource->loader() && response.httpStatusCode() >= 400 && |
| 1255 !resource->shouldIgnoreHTTPStatusCodeErrors()) { | 1265 !resource->shouldIgnoreHTTPStatusCodeErrors()) { |
| 1256 resource->loader()->didFail(ResourceError::cancelledError(response.url())); | 1266 resource->loader()->didFail(ResourceError::cancelledError(response.url())); |
| 1257 } | 1267 } |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1356 bool ResourceFetcher::defersLoading() const { | 1366 bool ResourceFetcher::defersLoading() const { |
| 1357 return context().defersLoading(); | 1367 return context().defersLoading(); |
| 1358 } | 1368 } |
| 1359 | 1369 |
| 1360 static bool isManualRedirectFetchRequest(const ResourceRequest& request) { | 1370 static bool isManualRedirectFetchRequest(const ResourceRequest& request) { |
| 1361 return request.fetchRedirectMode() == | 1371 return request.fetchRedirectMode() == |
| 1362 WebURLRequest::FetchRedirectModeManual && | 1372 WebURLRequest::FetchRedirectModeManual && |
| 1363 request.requestContext() == WebURLRequest::RequestContextFetch; | 1373 request.requestContext() == WebURLRequest::RequestContextFetch; |
| 1364 } | 1374 } |
| 1365 | 1375 |
| 1366 bool ResourceFetcher::willFollowRedirect( | 1376 ResourceRequestBlockedReason ResourceFetcher::willFollowRedirect( |
| 1367 Resource* resource, | 1377 Resource* resource, |
| 1368 ResourceRequest& newRequest, | 1378 ResourceRequest& newRequest, |
| 1369 const ResourceResponse& redirectResponse) { | 1379 const ResourceResponse& redirectResponse) { |
| 1370 if (!isManualRedirectFetchRequest(resource->resourceRequest())) { | 1380 if (!isManualRedirectFetchRequest(resource->resourceRequest())) { |
| 1371 if (!context().canRequest(resource->getType(), newRequest, newRequest.url(), | 1381 ResourceRequestBlockedReason blockedReason = |
| 1372 resource->options(), resource->isUnusedPreload(), | 1382 context().canRequest(resource->getType(), newRequest, newRequest.url(), |
| 1373 FetchRequest::UseDefaultOriginRestrictionForType)) | 1383 resource->options(), resource->isUnusedPreload(), |
| 1374 return false; | 1384 FetchRequest::UseDefaultOriginRestrictionForType); |
| 1385 if (blockedReason != ResourceRequestBlockedReason::None) |
| 1386 return blockedReason; |
| 1375 if (resource->options().corsEnabled == IsCORSEnabled) { | 1387 if (resource->options().corsEnabled == IsCORSEnabled) { |
| 1376 RefPtr<SecurityOrigin> sourceOrigin = resource->options().securityOrigin; | 1388 RefPtr<SecurityOrigin> sourceOrigin = resource->options().securityOrigin; |
| 1377 if (!sourceOrigin.get()) | 1389 if (!sourceOrigin.get()) |
| 1378 sourceOrigin = context().getSecurityOrigin(); | 1390 sourceOrigin = context().getSecurityOrigin(); |
| 1379 | 1391 |
| 1380 String errorMessage; | 1392 String errorMessage; |
| 1381 StoredCredentials withCredentials = | 1393 StoredCredentials withCredentials = |
| 1382 resource->lastResourceRequest().allowStoredCredentials() | 1394 resource->lastResourceRequest().allowStoredCredentials() |
| 1383 ? AllowStoredCredentials | 1395 ? AllowStoredCredentials |
| 1384 : DoNotAllowStoredCredentials; | 1396 : DoNotAllowStoredCredentials; |
| 1385 if (!CrossOriginAccessControl::handleRedirect( | 1397 if (!CrossOriginAccessControl::handleRedirect( |
| 1386 sourceOrigin, newRequest, redirectResponse, withCredentials, | 1398 sourceOrigin, newRequest, redirectResponse, withCredentials, |
| 1387 resource->mutableOptions(), errorMessage)) { | 1399 resource->mutableOptions(), errorMessage)) { |
| 1388 resource->setCORSFailed(); | 1400 resource->setCORSFailed(); |
| 1389 context().addConsoleMessage(errorMessage); | 1401 context().addConsoleMessage(errorMessage); |
| 1390 return false; | 1402 return ResourceRequestBlockedReason::Other; |
| 1391 } | 1403 } |
| 1392 } | 1404 } |
| 1393 if (resource->getType() == Resource::Image && | 1405 if (resource->getType() == Resource::Image && |
| 1394 shouldDeferImageLoad(newRequest.url())) | 1406 shouldDeferImageLoad(newRequest.url())) { |
| 1395 return false; | 1407 return ResourceRequestBlockedReason::Other; |
| 1408 } |
| 1396 } | 1409 } |
| 1397 | 1410 |
| 1398 ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource); | 1411 ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource); |
| 1399 if (it != m_resourceTimingInfoMap.end()) { | 1412 if (it != m_resourceTimingInfoMap.end()) { |
| 1400 bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url()); | 1413 bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url()); |
| 1401 it->value->addRedirect(redirectResponse, crossOrigin); | 1414 it->value->addRedirect(redirectResponse, crossOrigin); |
| 1402 } | 1415 } |
| 1403 newRequest.setAllowStoredCredentials(resource->options().allowCredentials == | 1416 newRequest.setAllowStoredCredentials(resource->options().allowCredentials == |
| 1404 AllowStoredCredentials); | 1417 AllowStoredCredentials); |
| 1405 willSendRequest(resource->identifier(), newRequest, redirectResponse, | 1418 willSendRequest(resource->identifier(), newRequest, redirectResponse, |
| 1406 resource->options()); | 1419 resource->options()); |
| 1407 return true; | 1420 return ResourceRequestBlockedReason::None; |
| 1408 } | 1421 } |
| 1409 | 1422 |
| 1410 void ResourceFetcher::willSendRequest(unsigned long identifier, | 1423 void ResourceFetcher::willSendRequest(unsigned long identifier, |
| 1411 ResourceRequest& newRequest, | 1424 ResourceRequest& newRequest, |
| 1412 const ResourceResponse& redirectResponse, | 1425 const ResourceResponse& redirectResponse, |
| 1413 const ResourceLoaderOptions& options) { | 1426 const ResourceLoaderOptions& options) { |
| 1414 context().dispatchWillSendRequest(identifier, newRequest, redirectResponse, | 1427 context().dispatchWillSendRequest(identifier, newRequest, redirectResponse, |
| 1415 options.initiatorInfo); | 1428 options.initiatorInfo); |
| 1416 } | 1429 } |
| 1417 | 1430 |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 visitor->trace(m_context); | 1668 visitor->trace(m_context); |
| 1656 visitor->trace(m_archive); | 1669 visitor->trace(m_archive); |
| 1657 visitor->trace(m_loaders); | 1670 visitor->trace(m_loaders); |
| 1658 visitor->trace(m_nonBlockingLoaders); | 1671 visitor->trace(m_nonBlockingLoaders); |
| 1659 visitor->trace(m_documentResources); | 1672 visitor->trace(m_documentResources); |
| 1660 visitor->trace(m_preloads); | 1673 visitor->trace(m_preloads); |
| 1661 visitor->trace(m_resourceTimingInfoMap); | 1674 visitor->trace(m_resourceTimingInfoMap); |
| 1662 } | 1675 } |
| 1663 | 1676 |
| 1664 } // namespace blink | 1677 } // namespace blink |
| OLD | NEW |