Chromium Code Reviews| 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 return ResourceLoadPriorityUnresolved; | 150 return ResourceLoadPriorityUnresolved; |
| 151 } | 151 } |
| 152 | 152 |
| 153 } // namespace | 153 } // namespace |
| 154 | 154 |
| 155 ResourceLoadPriority ResourceFetcher::computeLoadPriority( | 155 ResourceLoadPriority ResourceFetcher::computeLoadPriority( |
| 156 Resource::Type type, | 156 Resource::Type type, |
| 157 const ResourceRequest& resourceRequest, | 157 const ResourceRequest& resourceRequest, |
| 158 ResourcePriority::VisibilityStatus visibility, | 158 ResourcePriority::VisibilityStatus visibility, |
| 159 FetchRequest::DeferOption deferOption, | 159 FetchRequest::DeferOption deferOption, |
| 160 bool forPreload) { | 160 bool speculativePreload) { |
| 161 ResourceLoadPriority priority = typeToPriority(type); | 161 ResourceLoadPriority priority = typeToPriority(type); |
| 162 | 162 |
| 163 // Visible resources (images in practice) get a boost to High priority. | 163 // Visible resources (images in practice) get a boost to High priority. |
| 164 if (visibility == ResourcePriority::Visible) | 164 if (visibility == ResourcePriority::Visible) |
| 165 priority = ResourceLoadPriorityHigh; | 165 priority = ResourceLoadPriorityHigh; |
| 166 | 166 |
| 167 // Resources before the first image are considered "early" in the document and | 167 // Resources before the first image are considered "early" in the document and |
| 168 // resources after the first image are "late" in the document. Important to | 168 // resources after the first image are "late" in the document. Important to |
| 169 // note that this is based on when the preload scanner discovers a resource | 169 // note that this is based on when the preload scanner discovers a resource |
| 170 // for the most part so the main parser may not have reached the image element | 170 // for the most part so the main parser may not have reached the image element |
| 171 // yet. | 171 // yet. |
| 172 if (type == Resource::Image) | 172 if (type == Resource::Image) |
| 173 m_imageFetched = true; | 173 m_imageFetched = true; |
| 174 | 174 |
| 175 if (FetchRequest::IdleLoad == deferOption) { | 175 if (FetchRequest::IdleLoad == deferOption) { |
| 176 priority = ResourceLoadPriorityVeryLow; | 176 priority = ResourceLoadPriorityVeryLow; |
| 177 } else if (type == Resource::Script) { | 177 } else if (type == Resource::Script) { |
| 178 // Special handling for scripts. | 178 // Special handling for scripts. |
| 179 // Default/Parser-Blocking/Preload early in document: High (set in | 179 // Default/Parser-Blocking/Preload early in document: High (set in |
| 180 // typeToPriority) | 180 // typeToPriority) |
| 181 // Async/Defer: Low Priority (applies to both preload and parser-inserted) | 181 // Async/Defer: Low Priority (applies to both preload and parser-inserted) |
| 182 // Preload late in document: Medium | 182 // Preload late in document: Medium |
| 183 if (FetchRequest::LazyLoad == deferOption) | 183 if (FetchRequest::LazyLoad == deferOption) { |
| 184 priority = ResourceLoadPriorityLow; | 184 priority = ResourceLoadPriorityLow; |
| 185 else if (forPreload && m_imageFetched) | 185 } else if (speculativePreload && m_imageFetched) { |
| 186 // TODO(yoav): It is not clear why this applies only to preloaded scripts. | |
| 186 priority = ResourceLoadPriorityMedium; | 187 priority = ResourceLoadPriorityMedium; |
| 188 } | |
| 187 } else if (FetchRequest::LazyLoad == deferOption) { | 189 } else if (FetchRequest::LazyLoad == deferOption) { |
| 188 priority = ResourceLoadPriorityVeryLow; | 190 priority = ResourceLoadPriorityVeryLow; |
| 189 } | 191 } |
| 190 | 192 |
| 191 // A manually set priority acts as a floor. This is used to ensure that | 193 // A manually set priority acts as a floor. This is used to ensure that |
| 192 // synchronous requests are always given the highest possible priority, as | 194 // synchronous requests are always given the highest possible priority, as |
| 193 // well as to ensure that there isn't priority churn if images move in and out | 195 // well as to ensure that there isn't priority churn if images move in and out |
| 194 // of the viewport, or is displayed more than once, both in and out of the | 196 // of the viewport, or is displayed more than once, both in and out of the |
| 195 // viewport. | 197 // viewport. |
| 196 return std::max(context().modifyPriorityForExperiments(priority), | 198 return std::max(context().modifyPriorityForExperiments(priority), |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 return resource.get(); | 271 return resource.get(); |
| 270 } | 272 } |
| 271 | 273 |
| 272 bool ResourceFetcher::isControlledByServiceWorker() const { | 274 bool ResourceFetcher::isControlledByServiceWorker() const { |
| 273 return context().isControlledByServiceWorker(); | 275 return context().isControlledByServiceWorker(); |
| 274 } | 276 } |
| 275 | 277 |
| 276 bool ResourceFetcher::resourceNeedsLoad(Resource* resource, | 278 bool ResourceFetcher::resourceNeedsLoad(Resource* resource, |
| 277 const FetchRequest& request, | 279 const FetchRequest& request, |
| 278 RevalidationPolicy policy) { | 280 RevalidationPolicy policy) { |
| 279 // Defer a font load until it is actually needed unless this is a preload. | 281 // Defer a font load until it is actually needed unless this is a link |
| 280 if (resource->getType() == Resource::Font && !request.forPreload()) | 282 // preload. |
|
Charlie Harrison
2017/02/05 18:39:12
I think this should still be for all preloads, not
Yoav Weiss
2017/02/06 09:58:35
I don't know that it's worth-while to pay for an e
Charlie Harrison
2017/02/06 19:54:15
Your call, it isn't a huge deal. Probably the best
| |
| 283 if (resource->getType() == Resource::Font && !request.isLinkPreload()) | |
| 281 return false; | 284 return false; |
| 282 if (resource->isImage() && shouldDeferImageLoad(resource->url())) | 285 if (resource->isImage() && shouldDeferImageLoad(resource->url())) |
| 283 return false; | 286 return false; |
| 284 return policy != Use || resource->stillNeedsLoad(); | 287 return policy != Use || resource->stillNeedsLoad(); |
| 285 } | 288 } |
| 286 | 289 |
| 287 // Limit the number of URLs in m_validatedURLs to avoid memory bloat. | 290 // Limit the number of URLs in m_validatedURLs to avoid memory bloat. |
| 288 // http://crbug.com/52411 | 291 // http://crbug.com/52411 |
| 289 static const int kMaxValidatedURLsSize = 10000; | 292 static const int kMaxValidatedURLsSize = 10000; |
| 290 | 293 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 } | 419 } |
| 417 | 420 |
| 418 void ResourceFetcher::moveCachedNonBlockingResourceToBlocking( | 421 void ResourceFetcher::moveCachedNonBlockingResourceToBlocking( |
| 419 Resource* resource, | 422 Resource* resource, |
| 420 const FetchRequest& request) { | 423 const FetchRequest& request) { |
| 421 // TODO(yoav): Test that non-blocking resources (video/audio/track) continue | 424 // TODO(yoav): Test that non-blocking resources (video/audio/track) continue |
| 422 // to not-block even after being preloaded and discovered. | 425 // to not-block even after being preloaded and discovered. |
| 423 if (resource && resource->loader() && | 426 if (resource && resource->loader() && |
| 424 resource->isLoadEventBlockingResourceType() && | 427 resource->isLoadEventBlockingResourceType() && |
| 425 m_nonBlockingLoaders.contains(resource->loader()) && | 428 m_nonBlockingLoaders.contains(resource->loader()) && |
| 426 resource->isLinkPreload() && !request.forPreload()) { | 429 resource->isLinkPreload() && !request.isLinkPreload()) { |
|
Charlie Harrison
2017/02/05 18:39:12
nit: can we move the isLinkPreload and !isLinkPrel
Yoav Weiss
2017/02/06 09:58:35
Good call
| |
| 427 m_nonBlockingLoaders.remove(resource->loader()); | 430 m_nonBlockingLoaders.remove(resource->loader()); |
|
Charlie Harrison
2017/02/05 18:39:12
I am slightly confused what this method does, do y
Yoav Weiss
2017/02/06 09:58:35
renamed the method to a hopefully clearer name, an
| |
| 428 m_loaders.insert(resource->loader()); | 431 m_loaders.insert(resource->loader()); |
| 429 } | 432 } |
| 430 } | 433 } |
| 431 | 434 |
| 432 void ResourceFetcher::updateMemoryCacheStats(Resource* resource, | 435 void ResourceFetcher::updateMemoryCacheStats(Resource* resource, |
| 433 RevalidationPolicy policy, | 436 RevalidationPolicy policy, |
| 434 const FetchRequest& request, | 437 const FetchRequest& request, |
| 435 const ResourceFactory& factory, | 438 const ResourceFactory& factory, |
| 436 bool isStaticData) const { | 439 bool isStaticData) const { |
| 437 if (isStaticData) | 440 if (isStaticData) |
| 438 return; | 441 return; |
| 439 | 442 |
| 440 if (request.forPreload()) { | 443 if (request.speculativePreload() || request.isLinkPreload()) { |
| 441 DEFINE_RESOURCE_HISTOGRAM("Preload."); | 444 DEFINE_RESOURCE_HISTOGRAM("Preload."); |
| 442 } else { | 445 } else { |
| 443 DEFINE_RESOURCE_HISTOGRAM(""); | 446 DEFINE_RESOURCE_HISTOGRAM(""); |
| 444 } | 447 } |
| 445 | 448 |
| 446 // Aims to count Resource only referenced from MemoryCache (i.e. what would be | 449 // Aims to count Resource only referenced from MemoryCache (i.e. what would be |
| 447 // dead if MemoryCache holds weak references to Resource). Currently we check | 450 // dead if MemoryCache holds weak references to Resource). Currently we check |
| 448 // references to Resource from ResourceClient and |m_preloads| only, because | 451 // references to Resource from ResourceClient and |m_preloads| only, because |
| 449 // they are major sources of references. | 452 // they are major sources of references. |
| 450 if (resource && !resource->isAlive() && | 453 if (resource && !resource->isAlive() && |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 467 | 470 |
| 468 context().populateResourceRequest( | 471 context().populateResourceRequest( |
| 469 factory.type(), request.clientHintsPreferences(), | 472 factory.type(), request.clientHintsPreferences(), |
| 470 request.getResourceWidth(), resourceRequest); | 473 request.getResourceWidth(), resourceRequest); |
| 471 | 474 |
| 472 if (!request.url().isValid()) | 475 if (!request.url().isValid()) |
| 473 return Abort; | 476 return Abort; |
| 474 | 477 |
| 475 resourceRequest.setPriority(computeLoadPriority( | 478 resourceRequest.setPriority(computeLoadPriority( |
| 476 factory.type(), request.resourceRequest(), ResourcePriority::NotVisible, | 479 factory.type(), request.resourceRequest(), ResourcePriority::NotVisible, |
| 477 request.defer(), request.forPreload())); | 480 request.defer(), request.speculativePreload())); |
| 478 initializeResourceRequest(resourceRequest, factory.type(), request.defer()); | 481 initializeResourceRequest(resourceRequest, factory.type(), request.defer()); |
| 479 network_instrumentation::resourcePrioritySet(identifier, | 482 network_instrumentation::resourcePrioritySet(identifier, |
| 480 resourceRequest.priority()); | 483 resourceRequest.priority()); |
| 481 | 484 |
| 482 blockedReason = context().canRequest( | 485 blockedReason = context().canRequest( |
| 483 factory.type(), resourceRequest, | 486 factory.type(), resourceRequest, |
| 484 MemoryCache::removeFragmentIdentifierIfNeeded(request.url()), | 487 MemoryCache::removeFragmentIdentifierIfNeeded(request.url()), |
| 485 request.options(), request.forPreload(), request.getOriginRestriction()); | 488 request.options(), request.speculativePreload(), |
| 489 request.getOriginRestriction()); | |
| 486 if (blockedReason != ResourceRequestBlockedReason::None) { | 490 if (blockedReason != ResourceRequestBlockedReason::None) { |
| 487 DCHECK(!substituteData.forceSynchronousLoad()); | 491 DCHECK(!substituteData.forceSynchronousLoad()); |
| 488 return Block; | 492 return Block; |
| 489 } | 493 } |
| 490 | 494 |
| 491 context().willStartLoadingResource( | 495 context().willStartLoadingResource( |
| 492 identifier, resourceRequest, factory.type(), | 496 identifier, resourceRequest, factory.type(), |
| 493 request.options().initiatorInfo.name, request.forPreload()); | 497 request.options().initiatorInfo.name, request.speculativePreload()); |
| 494 if (!request.url().isValid()) | 498 if (!request.url().isValid()) |
| 495 return Abort; | 499 return Abort; |
| 496 | 500 |
| 497 resourceRequest.setAllowStoredCredentials( | 501 resourceRequest.setAllowStoredCredentials( |
| 498 request.options().allowCredentials == AllowStoredCredentials); | 502 request.options().allowCredentials == AllowStoredCredentials); |
| 499 return Continue; | 503 return Continue; |
| 500 } | 504 } |
| 501 | 505 |
| 502 Resource* ResourceFetcher::requestResource( | 506 Resource* ResourceFetcher::requestResource( |
| 503 FetchRequest& request, | 507 FetchRequest& request, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 561 initializeRevalidation(resourceRequest, resource); | 565 initializeRevalidation(resourceRequest, resource); |
| 562 break; | 566 break; |
| 563 case Use: | 567 case Use: |
| 564 if (resource->isLinkPreload() && !request.isLinkPreload()) | 568 if (resource->isLinkPreload() && !request.isLinkPreload()) |
| 565 resource->setLinkPreload(false); | 569 resource->setLinkPreload(false); |
| 566 break; | 570 break; |
| 567 } | 571 } |
| 568 if (!resource) | 572 if (!resource) |
| 569 return nullptr; | 573 return nullptr; |
| 570 if (resource->getType() != factory.type()) { | 574 if (resource->getType() != factory.type()) { |
| 571 DCHECK(request.forPreload()); | 575 DCHECK(request.speculativePreload() || request.isLinkPreload()); |
| 576 // TODO(yoav): What's the scenario where this can actually happen? | |
| 572 return nullptr; | 577 return nullptr; |
| 573 } | 578 } |
| 574 | 579 |
| 575 if (!resource->isAlive()) | 580 if (!resource->isAlive()) |
| 576 m_deadStatsRecorder.update(policy); | 581 m_deadStatsRecorder.update(policy); |
| 577 | 582 |
| 578 if (policy != Use) | 583 if (policy != Use) |
| 579 resource->setIdentifier(identifier); | 584 resource->setIdentifier(identifier); |
| 580 | 585 |
| 581 if (!request.forPreload() || policy != Use) { | 586 // TODO(yoav): It is not clear why preloads are exempt from this check. Can we |
| 587 // remove the exemption? | |
| 588 if (!request.speculativePreload() || policy != Use) { | |
| 582 // When issuing another request for a resource that is already in-flight | 589 // When issuing another request for a resource that is already in-flight |
| 583 // make sure to not demote the priority of the in-flight request. If the new | 590 // make sure to not demote the priority of the in-flight request. If the new |
| 584 // request isn't at the same priority as the in-flight request, only allow | 591 // request isn't at the same priority as the in-flight request, only allow |
| 585 // promotions. This can happen when a visible image's priority is increased | 592 // promotions. This can happen when a visible image's priority is increased |
| 586 // and then another reference to the image is parsed (which would be at a | 593 // and then another reference to the image is parsed (which would be at a |
| 587 // lower priority). | 594 // lower priority). |
| 588 if (resourceRequest.priority() > resource->resourceRequest().priority()) | 595 if (resourceRequest.priority() > resource->resourceRequest().priority()) |
| 589 resource->didChangePriority(resourceRequest.priority(), 0); | 596 resource->didChangePriority(resourceRequest.priority(), 0); |
| 597 // TODO(yoav): I'd expect the stated scenario to not go here, as its policy | |
| 598 // would be Use. | |
| 590 } | 599 } |
| 591 | 600 |
| 592 // If only the fragment identifiers differ, it is the same resource. | 601 // If only the fragment identifiers differ, it is the same resource. |
| 593 DCHECK(equalIgnoringFragmentIdentifier(resource->url(), request.url())); | 602 DCHECK(equalIgnoringFragmentIdentifier(resource->url(), request.url())); |
| 594 requestLoadStarted( | 603 requestLoadStarted( |
| 595 identifier, resource, request, | 604 identifier, resource, request, |
| 596 policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork, | 605 policy == Use ? ResourceLoadingFromCache : ResourceLoadingFromNetwork, |
| 597 isStaticData); | 606 isStaticData); |
| 598 m_documentResources.set( | 607 m_documentResources.set( |
| 599 MemoryCache::removeFragmentIdentifierIfNeeded(request.url()), resource); | 608 MemoryCache::removeFragmentIdentifierIfNeeded(request.url()), resource); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 701 const String cacheIdentifier = getCacheIdentifier(); | 710 const String cacheIdentifier = getCacheIdentifier(); |
| 702 DCHECK(!memoryCache()->resourceForURL(request.resourceRequest().url(), | 711 DCHECK(!memoryCache()->resourceForURL(request.resourceRequest().url(), |
| 703 cacheIdentifier)); | 712 cacheIdentifier)); |
| 704 | 713 |
| 705 RESOURCE_LOADING_DVLOG(1) << "Loading Resource for " | 714 RESOURCE_LOADING_DVLOG(1) << "Loading Resource for " |
| 706 << request.resourceRequest().url().elidedString(); | 715 << request.resourceRequest().url().elidedString(); |
| 707 | 716 |
| 708 Resource* resource = | 717 Resource* resource = |
| 709 factory.create(request.resourceRequest(), request.options(), charset); | 718 factory.create(request.resourceRequest(), request.options(), charset); |
| 710 resource->setLinkPreload(request.isLinkPreload()); | 719 resource->setLinkPreload(request.isLinkPreload()); |
| 711 if (request.forPreload()) { | 720 if (request.speculativePreload()) { |
| 712 resource->setPreloadDiscoveryTime(request.preloadDiscoveryTime()); | 721 resource->setPreloadDiscoveryTime(request.preloadDiscoveryTime()); |
| 713 } | 722 } |
| 714 resource->setCacheIdentifier(cacheIdentifier); | 723 resource->setCacheIdentifier(cacheIdentifier); |
| 715 | 724 |
| 716 // - Don't add main resource to cache to prevent reuse. | 725 // - Don't add main resource to cache to prevent reuse. |
| 717 // - Don't add the resource if its body will not be stored. | 726 // - Don't add the resource if its body will not be stored. |
| 718 if (factory.type() != Resource::MainResource && | 727 if (factory.type() != Resource::MainResource && |
| 719 request.options().dataBufferingPolicy != DoNotBufferData) { | 728 request.options().dataBufferingPolicy != DoNotBufferData) { |
| 720 memoryCache()->add(resource); | 729 memoryCache()->add(resource); |
| 721 } | 730 } |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 804 if (existingResource->mustRefetchDueToIntegrityMetadata(fetchRequest)) { | 813 if (existingResource->mustRefetchDueToIntegrityMetadata(fetchRequest)) { |
| 805 RecordSriResourceIntegrityMismatchEvent(RefetchDueToIntegrityMismatch); | 814 RecordSriResourceIntegrityMismatchEvent(RefetchDueToIntegrityMismatch); |
| 806 return Reload; | 815 return Reload; |
| 807 } | 816 } |
| 808 | 817 |
| 809 // Service Worker's CORS fallback message must not be cached. | 818 // Service Worker's CORS fallback message must not be cached. |
| 810 if (existingResource->response().wasFallbackRequiredByServiceWorker()) | 819 if (existingResource->response().wasFallbackRequiredByServiceWorker()) |
| 811 return Reload; | 820 return Reload; |
| 812 | 821 |
| 813 // We already have a preload going for this URL. | 822 // We already have a preload going for this URL. |
| 814 if (fetchRequest.forPreload() && existingResource->isPreloaded()) | 823 if (fetchRequest.speculativePreload() && existingResource->isPreloaded()) |
| 815 return Use; | 824 return Use; |
| 816 | 825 |
| 817 // If the same URL has been loaded as a different type, we need to reload. | 826 // If the same URL has been loaded as a different type, we need to reload. |
| 818 if (existingResource->getType() != type) { | 827 if (existingResource->getType() != type) { |
| 819 // FIXME: If existingResource is a Preload and the new type is LinkPrefetch | 828 // FIXME: If existingResource is a Preload and the new type is LinkPrefetch |
| 820 // We really should discard the new prefetch since the preload has more | 829 // We really should discard the new prefetch since the preload has more |
| 821 // specific type information! crbug.com/379893 | 830 // specific type information! crbug.com/379893 |
| 822 // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case. | 831 // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case. |
| 823 RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy " | 832 RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy " |
| 824 "reloading due to type mismatch."; | 833 "reloading due to type mismatch."; |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1525 visitor->trace(m_context); | 1534 visitor->trace(m_context); |
| 1526 visitor->trace(m_archive); | 1535 visitor->trace(m_archive); |
| 1527 visitor->trace(m_loaders); | 1536 visitor->trace(m_loaders); |
| 1528 visitor->trace(m_nonBlockingLoaders); | 1537 visitor->trace(m_nonBlockingLoaders); |
| 1529 visitor->trace(m_documentResources); | 1538 visitor->trace(m_documentResources); |
| 1530 visitor->trace(m_preloads); | 1539 visitor->trace(m_preloads); |
| 1531 visitor->trace(m_resourceTimingInfoMap); | 1540 visitor->trace(m_resourceTimingInfoMap); |
| 1532 } | 1541 } |
| 1533 | 1542 |
| 1534 } // namespace blink | 1543 } // namespace blink |
| OLD | NEW |