Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(464)

Side by Side Diff: third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp

Issue 2535383003: Collapse images disallowed by the Safe Browsing Subresource Filter. (Closed)
Patch Set: Initial draft. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 if (!request.url().isValid()) 509 if (!request.url().isValid())
506 return nullptr; 510 return nullptr;
507 511
508 request.mutableResourceRequest().setPriority(computeLoadPriority( 512 request.mutableResourceRequest().setPriority(computeLoadPriority(
509 factory.type(), request, ResourcePriority::NotVisible)); 513 factory.type(), request, ResourcePriority::NotVisible));
510 initializeResourceRequest(request.mutableResourceRequest(), factory.type(), 514 initializeResourceRequest(request.mutableResourceRequest(), factory.type(),
511 request.defer()); 515 request.defer());
512 network_instrumentation::resourcePrioritySet( 516 network_instrumentation::resourcePrioritySet(
513 identifier, request.resourceRequest().priority()); 517 identifier, request.resourceRequest().priority());
514 518
515 if (!context().canRequest( 519 ResourceRequestBlockedReason blockedReason = context().canRequest(
516 factory.type(), request.resourceRequest(), 520 factory.type(), request.resourceRequest(),
517 MemoryCache::removeFragmentIdentifierIfNeeded(request.url()), 521 MemoryCache::removeFragmentIdentifierIfNeeded(request.url()),
518 request.options(), request.forPreload(), 522 request.options(), request.forPreload(), request.getOriginRestriction());
519 request.getOriginRestriction())) { 523 if (blockedReason != ResourceRequestBlockedReason::None) {
520 DCHECK(!substituteData.forceSynchronousLoad()); 524 DCHECK(!substituteData.forceSynchronousLoad());
521 return resourceForBlockedRequest(request, factory); 525 return resourceForBlockedRequest(request, factory, blockedReason);
522 } 526 }
523 527
524 context().willStartLoadingResource( 528 context().willStartLoadingResource(
525 identifier, request.mutableResourceRequest(), factory.type()); 529 identifier, request.mutableResourceRequest(), factory.type());
526 if (!request.url().isValid()) 530 if (!request.url().isValid())
527 return nullptr; 531 return nullptr;
528 532
529 if (!request.forPreload()) { 533 if (!request.forPreload()) {
530 V8DOMActivityLogger* activityLogger = nullptr; 534 V8DOMActivityLogger* activityLogger = nullptr;
531 if (request.options().initiatorInfo.name == 535 if (request.options().initiatorInfo.name ==
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
1224 resource->loader()->restart(request, context().loadingTaskRunner(), 1228 resource->loader()->restart(request, context().loadingTaskRunner(),
1225 context().defersLoading()); 1229 context().defersLoading());
1226 return; 1230 return;
1227 } 1231 }
1228 1232
1229 // If the response is fetched via ServiceWorker, the original URL of the 1233 // If the response is fetched via ServiceWorker, the original URL of the
1230 // response could be different from the URL of the request. We check the URL 1234 // response could be different from the URL of the request. We check the URL
1231 // not to load the resources which are forbidden by the page CSP. 1235 // not to load the resources which are forbidden by the page CSP.
1232 // https://w3c.github.io/webappsec-csp/#should-block-response 1236 // https://w3c.github.io/webappsec-csp/#should-block-response
1233 const KURL& originalURL = response.originalURLViaServiceWorker(); 1237 const KURL& originalURL = response.originalURLViaServiceWorker();
1234 if (!originalURL.isEmpty() && 1238 if (!originalURL.isEmpty()) {
1235 !context().allowResponse(resource->getType(), 1239 ResourceRequestBlockedReason blockedReason = context().allowResponse(
1236 resource->resourceRequest(), originalURL, 1240 resource->getType(), resource->resourceRequest(), originalURL,
1237 resource->options())) { 1241 resource->options());
1238 resource->loader()->didFail( 1242 if (blockedReason != ResourceRequestBlockedReason::None) {
1239 ResourceError::cancelledDueToAccessCheckError(originalURL)); 1243 resource->loader()->didFail(
1244 ResourceError::cancelledDueToAccessCheckError(originalURL,
1245 blockedReason));
1246 return;
1247 }
1248 }
1249 } else if (resource->options().corsEnabled == IsCORSEnabled) {
1250 ResourceRequestBlockedReason blockedReason =
1251 canAccessResponse(resource, response);
1252 if (blockedReason != ResourceRequestBlockedReason::None) {
1253 resource->loader()->didFail(ResourceError::cancelledDueToAccessCheckError(
1254 response.url(), blockedReason));
1240 return; 1255 return;
1241 } 1256 }
1242 } else if (resource->options().corsEnabled == IsCORSEnabled &&
1243 !canAccessResponse(resource, response)) {
1244 resource->loader()->didFail(
1245 ResourceError::cancelledDueToAccessCheckError(response.url()));
1246 return;
1247 } 1257 }
1248 1258
1249 context().dispatchDidReceiveResponse( 1259 context().dispatchDidReceiveResponse(
1250 resource->identifier(), response, resource->resourceRequest().frameType(), 1260 resource->identifier(), response, resource->resourceRequest().frameType(),
1251 resource->resourceRequest().requestContext(), resource); 1261 resource->resourceRequest().requestContext(), resource);
1252 resource->responseReceived(response, std::move(handle)); 1262 resource->responseReceived(response, std::move(handle));
1253 if (resource->loader() && response.httpStatusCode() >= 400 && 1263 if (resource->loader() && response.httpStatusCode() >= 400 &&
1254 !resource->shouldIgnoreHTTPStatusCodeErrors()) { 1264 !resource->shouldIgnoreHTTPStatusCodeErrors()) {
1255 resource->loader()->didFail(ResourceError::cancelledError(response.url())); 1265 resource->loader()->didFail(ResourceError::cancelledError(response.url()));
1256 } 1266 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1359 bool ResourceFetcher::defersLoading() const { 1369 bool ResourceFetcher::defersLoading() const {
1360 return context().defersLoading(); 1370 return context().defersLoading();
1361 } 1371 }
1362 1372
1363 static bool isManualRedirectFetchRequest(const ResourceRequest& request) { 1373 static bool isManualRedirectFetchRequest(const ResourceRequest& request) {
1364 return request.fetchRedirectMode() == 1374 return request.fetchRedirectMode() ==
1365 WebURLRequest::FetchRedirectModeManual && 1375 WebURLRequest::FetchRedirectModeManual &&
1366 request.requestContext() == WebURLRequest::RequestContextFetch; 1376 request.requestContext() == WebURLRequest::RequestContextFetch;
1367 } 1377 }
1368 1378
1369 bool ResourceFetcher::willFollowRedirect( 1379 ResourceRequestBlockedReason ResourceFetcher::willFollowRedirect(
1370 Resource* resource, 1380 Resource* resource,
1371 ResourceRequest& newRequest, 1381 ResourceRequest& newRequest,
1372 const ResourceResponse& redirectResponse) { 1382 const ResourceResponse& redirectResponse) {
1373 if (!isManualRedirectFetchRequest(resource->resourceRequest())) { 1383 if (!isManualRedirectFetchRequest(resource->resourceRequest())) {
1374 if (!context().canRequest(resource->getType(), newRequest, newRequest.url(), 1384 ResourceRequestBlockedReason blockedReason =
1375 resource->options(), resource->isUnusedPreload(), 1385 context().canRequest(resource->getType(), newRequest, newRequest.url(),
1376 FetchRequest::UseDefaultOriginRestrictionForType)) 1386 resource->options(), resource->isUnusedPreload(),
1377 return false; 1387 FetchRequest::UseDefaultOriginRestrictionForType);
1388 if (blockedReason != ResourceRequestBlockedReason::None)
1389 return blockedReason;
1378 if (resource->options().corsEnabled == IsCORSEnabled) { 1390 if (resource->options().corsEnabled == IsCORSEnabled) {
1379 RefPtr<SecurityOrigin> sourceOrigin = resource->options().securityOrigin; 1391 RefPtr<SecurityOrigin> sourceOrigin = resource->options().securityOrigin;
1380 if (!sourceOrigin.get()) 1392 if (!sourceOrigin.get())
1381 sourceOrigin = context().getSecurityOrigin(); 1393 sourceOrigin = context().getSecurityOrigin();
1382 1394
1383 String errorMessage; 1395 String errorMessage;
1384 StoredCredentials withCredentials = 1396 StoredCredentials withCredentials =
1385 resource->lastResourceRequest().allowStoredCredentials() 1397 resource->lastResourceRequest().allowStoredCredentials()
1386 ? AllowStoredCredentials 1398 ? AllowStoredCredentials
1387 : DoNotAllowStoredCredentials; 1399 : DoNotAllowStoredCredentials;
1388 if (!CrossOriginAccessControl::handleRedirect( 1400 if (!CrossOriginAccessControl::handleRedirect(
1389 sourceOrigin, newRequest, redirectResponse, withCredentials, 1401 sourceOrigin, newRequest, redirectResponse, withCredentials,
1390 resource->mutableOptions(), errorMessage)) { 1402 resource->mutableOptions(), errorMessage)) {
1391 resource->setCORSFailed(); 1403 resource->setCORSFailed();
1392 context().addConsoleMessage(errorMessage); 1404 context().addConsoleMessage(errorMessage);
1393 return false; 1405 return ResourceRequestBlockedReason::Other;
1394 } 1406 }
1395 } 1407 }
1396 if (resource->getType() == Resource::Image && 1408 if (resource->getType() == Resource::Image &&
1397 shouldDeferImageLoad(newRequest.url())) 1409 shouldDeferImageLoad(newRequest.url())) {
1398 return false; 1410 return ResourceRequestBlockedReason::Other;
1411 }
1399 } 1412 }
1400 1413
1401 ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource); 1414 ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource);
1402 if (it != m_resourceTimingInfoMap.end()) { 1415 if (it != m_resourceTimingInfoMap.end()) {
1403 bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url()); 1416 bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url());
1404 it->value->addRedirect(redirectResponse, crossOrigin); 1417 it->value->addRedirect(redirectResponse, crossOrigin);
1405 } 1418 }
1406 newRequest.setAllowStoredCredentials(resource->options().allowCredentials == 1419 newRequest.setAllowStoredCredentials(resource->options().allowCredentials ==
1407 AllowStoredCredentials); 1420 AllowStoredCredentials);
1408 willSendRequest(resource->identifier(), newRequest, redirectResponse, 1421 willSendRequest(resource->identifier(), newRequest, redirectResponse,
1409 resource->options()); 1422 resource->options());
1410 return true; 1423 return ResourceRequestBlockedReason::None;
1411 } 1424 }
1412 1425
1413 void ResourceFetcher::willSendRequest(unsigned long identifier, 1426 void ResourceFetcher::willSendRequest(unsigned long identifier,
1414 ResourceRequest& newRequest, 1427 ResourceRequest& newRequest,
1415 const ResourceResponse& redirectResponse, 1428 const ResourceResponse& redirectResponse,
1416 const ResourceLoaderOptions& options) { 1429 const ResourceLoaderOptions& options) {
1417 context().dispatchWillSendRequest(identifier, newRequest, redirectResponse, 1430 context().dispatchWillSendRequest(identifier, newRequest, redirectResponse,
1418 options.initiatorInfo); 1431 options.initiatorInfo);
1419 } 1432 }
1420 1433
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 visitor->trace(m_context); 1654 visitor->trace(m_context);
1642 visitor->trace(m_archive); 1655 visitor->trace(m_archive);
1643 visitor->trace(m_loaders); 1656 visitor->trace(m_loaders);
1644 visitor->trace(m_nonBlockingLoaders); 1657 visitor->trace(m_nonBlockingLoaders);
1645 visitor->trace(m_documentResources); 1658 visitor->trace(m_documentResources);
1646 visitor->trace(m_preloads); 1659 visitor->trace(m_preloads);
1647 visitor->trace(m_resourceTimingInfoMap); 1660 visitor->trace(m_resourceTimingInfoMap);
1648 } 1661 }
1649 1662
1650 } // namespace blink 1663 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698