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 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 if (params.IsSpeculativePreload() || params.IsLinkPreload()) { | 486 if (params.IsSpeculativePreload() || params.IsLinkPreload()) { |
487 DEFINE_RESOURCE_HISTOGRAM("Preload."); | 487 DEFINE_RESOURCE_HISTOGRAM("Preload."); |
488 } else { | 488 } else { |
489 DEFINE_RESOURCE_HISTOGRAM(""); | 489 DEFINE_RESOURCE_HISTOGRAM(""); |
490 } | 490 } |
491 | 491 |
492 // Aims to count Resource only referenced from MemoryCache (i.e. what would be | 492 // Aims to count Resource only referenced from MemoryCache (i.e. what would be |
493 // dead if MemoryCache holds weak references to Resource). Currently we check | 493 // dead if MemoryCache holds weak references to Resource). Currently we check |
494 // references to Resource from ResourceClient and |m_preloads| only, because | 494 // references to Resource from ResourceClient and |m_preloads| only, because |
495 // they are major sources of references. | 495 // they are major sources of references. |
496 if (resource && !resource->IsAlive() && !preloads_.Contains(resource)) { | 496 if (resource && !resource->IsAlive() && !ContainsAsPreload(resource)) { |
497 DEFINE_RESOURCE_HISTOGRAM("Dead."); | 497 DEFINE_RESOURCE_HISTOGRAM("Dead."); |
498 } | 498 } |
499 } | 499 } |
500 | 500 |
| 501 bool ResourceFetcher::ContainsAsPreload(Resource* resource) const { |
| 502 auto it = preloads_.find(PreloadKey(resource->Url(), resource->GetType())); |
| 503 return it != preloads_.end() && it->value == resource; |
| 504 } |
| 505 |
| 506 void ResourceFetcher::RemovePreload(Resource* resource) { |
| 507 auto it = preloads_.find(PreloadKey(resource->Url(), resource->GetType())); |
| 508 if (it == preloads_.end()) |
| 509 return; |
| 510 if (it->value == resource) { |
| 511 resource->DecreasePreloadCount(); |
| 512 preloads_.erase(it); |
| 513 } |
| 514 } |
| 515 |
501 ResourceFetcher::PrepareRequestResult ResourceFetcher::PrepareRequest( | 516 ResourceFetcher::PrepareRequestResult ResourceFetcher::PrepareRequest( |
502 FetchParameters& params, | 517 FetchParameters& params, |
503 const ResourceFactory& factory, | 518 const ResourceFactory& factory, |
504 const SubstituteData& substitute_data, | 519 const SubstituteData& substitute_data, |
505 unsigned long identifier, | 520 unsigned long identifier, |
506 ResourceRequestBlockedReason& blocked_reason) { | 521 ResourceRequestBlockedReason& blocked_reason) { |
507 ResourceRequest& resource_request = params.MutableResourceRequest(); | 522 ResourceRequest& resource_request = params.MutableResourceRequest(); |
508 | 523 |
509 DCHECK(params.Options().synchronous_policy == kRequestAsynchronously || | 524 DCHECK(params.Options().synchronous_policy == kRequestAsynchronously || |
510 factory.GetType() == Resource::kRaw || | 525 factory.GetType() == Resource::kRaw || |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 bool is_static_data = is_data_url || substitute_data.IsValid() || archive_; | 612 bool is_static_data = is_data_url || substitute_data.IsValid() || archive_; |
598 if (is_static_data) { | 613 if (is_static_data) { |
599 resource = ResourceForStaticData(params, factory, substitute_data); | 614 resource = ResourceForStaticData(params, factory, substitute_data); |
600 // Abort the request if the archive doesn't contain the resource, except in | 615 // Abort the request if the archive doesn't contain the resource, except in |
601 // the case of data URLs which might have resources such as fonts that need | 616 // the case of data URLs which might have resources such as fonts that need |
602 // to be decoded only on demand. These data URLs are allowed to be | 617 // to be decoded only on demand. These data URLs are allowed to be |
603 // processed using the normal ResourceFetcher machinery. | 618 // processed using the normal ResourceFetcher machinery. |
604 if (!resource && !is_data_url && archive_) | 619 if (!resource && !is_data_url && archive_) |
605 return nullptr; | 620 return nullptr; |
606 } | 621 } |
607 if (!resource && IsMainThread()) { | 622 RevalidationPolicy policy = kLoad; |
608 resource = | 623 bool preload_found = false; |
609 GetMemoryCache()->ResourceForURL(params.Url(), GetCacheIdentifier()); | 624 if (!resource) { |
| 625 resource = MatchPreload(params, factory.GetType()); |
| 626 if (resource) { |
| 627 preload_found = true; |
| 628 policy = kUse; |
| 629 // If |param| is for a blocking resource and a preloaded resource is |
| 630 // found, we may need to make it block the onload event. |
| 631 MakePreloadedResourceBlockOnloadIfNeeded(resource, params); |
| 632 } |
610 } | 633 } |
| 634 if (!preload_found) { |
| 635 if (!resource && IsMainThread()) { |
| 636 resource = |
| 637 GetMemoryCache()->ResourceForURL(params.Url(), GetCacheIdentifier()); |
| 638 } |
611 | 639 |
612 // If we got a preloaded resource from the cache for a non-preload request, | 640 policy = DetermineRevalidationPolicy(factory.GetType(), params, resource, |
613 // we may need to make it block the onload event. | 641 is_static_data); |
614 MakePreloadedResourceBlockOnloadIfNeeded(resource, params); | 642 TRACE_EVENT_INSTANT1( |
615 | 643 "blink", "ResourceFetcher::determineRevalidationPolicy", |
616 const RevalidationPolicy policy = DetermineRevalidationPolicy( | 644 TRACE_EVENT_SCOPE_THREAD, "revalidationPolicy", policy); |
617 factory.GetType(), params, resource, is_static_data); | 645 } |
618 TRACE_EVENT_INSTANT1("blink", "ResourceFetcher::determineRevalidationPolicy", | |
619 TRACE_EVENT_SCOPE_THREAD, "revalidationPolicy", policy); | |
620 | 646 |
621 UpdateMemoryCacheStats(resource, policy, params, factory, is_static_data); | 647 UpdateMemoryCacheStats(resource, policy, params, factory, is_static_data); |
622 | 648 |
623 switch (policy) { | 649 switch (policy) { |
624 case kReload: | 650 case kReload: |
625 GetMemoryCache()->Remove(resource); | 651 GetMemoryCache()->Remove(resource); |
626 // Fall through | 652 // Fall through |
627 case kLoad: | 653 case kLoad: |
628 resource = CreateResourceForLoading(params, params.Charset(), factory); | 654 resource = CreateResourceForLoading(params, params.Charset(), factory); |
629 break; | 655 break; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 // If only the fragment identifiers differ, it is the same resource. | 688 // If only the fragment identifiers differ, it is the same resource. |
663 DCHECK(EqualIgnoringFragmentIdentifier(resource->Url(), params.Url())); | 689 DCHECK(EqualIgnoringFragmentIdentifier(resource->Url(), params.Url())); |
664 RequestLoadStarted(identifier, resource, params, policy, is_static_data); | 690 RequestLoadStarted(identifier, resource, params, policy, is_static_data); |
665 document_resources_.Set( | 691 document_resources_.Set( |
666 MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()), resource); | 692 MemoryCache::RemoveFragmentIdentifierIfNeeded(params.Url()), resource); |
667 | 693 |
668 // Returns with an existing resource if the resource does not need to start | 694 // Returns with an existing resource if the resource does not need to start |
669 // loading immediately. If revalidation policy was determined as |Revalidate|, | 695 // loading immediately. If revalidation policy was determined as |Revalidate|, |
670 // the resource was already initialized for the revalidation here, but won't | 696 // the resource was already initialized for the revalidation here, but won't |
671 // start loading. | 697 // start loading. |
672 if (!ResourceNeedsLoad(resource, params, policy)) | 698 if (!ResourceNeedsLoad(resource, params, policy)) { |
| 699 if (policy != kUse) |
| 700 InsertAsPreloadIfNecessary(resource, params, factory.GetType()); |
673 return resource; | 701 return resource; |
| 702 } |
674 | 703 |
675 if (!StartLoad(resource)) | 704 if (!StartLoad(resource)) |
676 return nullptr; | 705 return nullptr; |
| 706 |
| 707 if (policy != kUse) |
| 708 InsertAsPreloadIfNecessary(resource, params, factory.GetType()); |
677 scoped_resource_load_tracker.ResourceLoadContinuesBeyondScope(); | 709 scoped_resource_load_tracker.ResourceLoadContinuesBeyondScope(); |
678 | 710 |
679 DCHECK(!resource->ErrorOccurred() || | 711 DCHECK(!resource->ErrorOccurred() || |
680 params.Options().synchronous_policy == kRequestSynchronously); | 712 params.Options().synchronous_policy == kRequestSynchronously); |
681 return resource; | 713 return resource; |
682 } | 714 } |
683 | 715 |
684 void ResourceFetcher::ResourceTimingReportTimerFired(TimerBase* timer) { | 716 void ResourceFetcher::ResourceTimingReportTimerFired(TimerBase* timer) { |
685 DCHECK_EQ(timer, &resource_timing_report_timer_); | 717 DCHECK_EQ(timer, &resource_timing_report_timer_); |
686 Vector<RefPtr<ResourceTimingInfo>> timing_reports; | 718 Vector<RefPtr<ResourceTimingInfo>> timing_reports; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
821 if (it != resource_timing_info_map_.end()) { | 853 if (it != resource_timing_info_map_.end()) { |
822 it->value->AddRedirect(redirect_response, cross_origin); | 854 it->value->AddRedirect(redirect_response, cross_origin); |
823 } | 855 } |
824 | 856 |
825 if (resource->GetType() == Resource::kMainResource) { | 857 if (resource->GetType() == Resource::kMainResource) { |
826 DCHECK(navigation_timing_info_); | 858 DCHECK(navigation_timing_info_); |
827 navigation_timing_info_->AddRedirect(redirect_response, cross_origin); | 859 navigation_timing_info_->AddRedirect(redirect_response, cross_origin); |
828 } | 860 } |
829 } | 861 } |
830 | 862 |
831 ResourceFetcher::RevalidationPolicy | 863 Resource* ResourceFetcher::MatchPreload(const FetchParameters& params, |
832 ResourceFetcher::DetermineRevalidationPolicy( | 864 Resource::Type type) { |
833 Resource::Type type, | 865 auto it = preloads_.find(PreloadKey(params.Url(), type)); |
834 const FetchParameters& fetch_params, | 866 if (it == preloads_.end()) |
835 Resource* existing_resource, | 867 return nullptr; |
836 bool is_static_data) const { | |
837 const ResourceRequest& request = fetch_params.GetResourceRequest(); | |
838 | 868 |
839 if (!existing_resource) | 869 Resource* resource = it->value; |
840 return kLoad; | |
841 | 870 |
842 // If the existing resource is loading and the associated fetcher is not equal | 871 RecordSriResourceIntegrityMismatchEvent(kCheckingForIntegrityMismatch); |
843 // to |this|, we must not use the resource. Otherwise, CSP violation may | 872 if (resource->MustRefetchDueToIntegrityMetadata(params)) |
844 // happen in redirect handling. | 873 return nullptr; |
845 if (existing_resource->Loader() && | 874 |
846 existing_resource->Loader()->Fetcher() != this) { | 875 if (params.IsSpeculativePreload()) |
847 return kReload; | 876 return resource; |
| 877 if (params.IsLinkPreload()) { |
| 878 resource->SetLinkPreload(true); |
| 879 return resource; |
848 } | 880 } |
849 | 881 |
850 // Checks if the resource has an explicit policy about integrity metadata. | 882 if (!IsReusableAlsoForPreloading(params, resource, false)) |
851 // | 883 return nullptr; |
852 // This is necessary because ScriptResource and CSSStyleSheetResource objects | 884 |
853 // do not keep the raw data around after the source is accessed once, so if | 885 resource->DecreasePreloadCount(); |
854 // the resource is accessed from the MemoryCache for a second time, there is | 886 preloads_.erase(it); |
855 // no way to redo an integrity check. | 887 matched_preloads_.push_back(resource); |
856 // | 888 return resource; |
857 // Thus, Blink implements a scheme where it caches the integrity information | 889 } |
858 // for those resources after the first time it is checked, and if there is | 890 |
859 // another request for that resource, with the same integrity metadata, Blink | 891 void ResourceFetcher::InsertAsPreloadIfNecessary(Resource* resource, |
860 // skips the integrity calculation. However, if the integrity metadata is a | 892 const FetchParameters& params, |
861 // mismatch, the MemoryCache must be skipped here, and a new request for the | 893 Resource::Type type) { |
862 // resource must be made to get the raw data. This is expected to be an | 894 if (!params.IsSpeculativePreload() && !params.IsLinkPreload()) |
863 // uncommon case, however, as it implies two same-origin requests to the same | 895 return; |
864 // resource, but with different integrity metadata. | 896 // CSP layout tests verify that preloads are subject to access checks by |
865 RecordSriResourceIntegrityMismatchEvent(kCheckingForIntegrityMismatch); | 897 // seeing if they are in the `preload started` list. Therefore do not add |
866 if (existing_resource->MustRefetchDueToIntegrityMetadata(fetch_params)) { | 898 // them to the list if the load is immediately denied. |
867 RecordSriResourceIntegrityMismatchEvent(kRefetchDueToIntegrityMismatch); | 899 if (resource->GetResourceError().IsAccessCheck()) |
868 return kReload; | 900 return; |
| 901 PreloadKey key(params.Url(), type); |
| 902 if (preloads_.find(key) == preloads_.end()) { |
| 903 preloads_.insert(key, resource); |
| 904 resource->IncreasePreloadCount(); |
| 905 if (preloaded_urls_for_test_) |
| 906 preloaded_urls_for_test_->insert(resource->Url().GetString()); |
869 } | 907 } |
| 908 } |
870 | 909 |
871 // If the same URL has been loaded as a different type, we need to reload. | 910 bool ResourceFetcher::IsReusableAlsoForPreloading(const FetchParameters& params, |
872 if (existing_resource->GetType() != type) { | 911 Resource* existing_resource, |
873 // FIXME: If existingResource is a Preload and the new type is LinkPrefetch | 912 bool is_static_data) const { |
874 // We really should discard the new prefetch since the preload has more | 913 const ResourceRequest& request = params.GetResourceRequest(); |
875 // specific type information! crbug.com/379893 | |
876 // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case. | |
877 RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy " | |
878 "reloading due to type mismatch."; | |
879 return kReload; | |
880 } | |
881 | |
882 // We already have a preload going for this URL. | |
883 if (fetch_params.IsSpeculativePreload() && existing_resource->IsPreloaded()) | |
884 return kUse; | |
885 | |
886 // Do not load from cache if images are not enabled. There are two general | 914 // Do not load from cache if images are not enabled. There are two general |
887 // cases: | 915 // cases: |
888 // | 916 // |
889 // 1. Images are disabled. Don't ever load images, even if the image is cached | 917 // 1. Images are disabled. Don't ever load images, even if the image is cached |
890 // or it is a data: url. In this case, we "Reload" the image, then defer it | 918 // or it is a data: url. In this case, we "Reload" the image, then defer it |
891 // with resourceNeedsLoad() so that it never actually goes to the network. | 919 // with resourceNeedsLoad() so that it never actually goes to the network. |
892 // | 920 // |
893 // 2. Images are enabled, but not loaded automatically. In this case, we will | 921 // 2. Images are enabled, but not loaded automatically. In this case, we will |
894 // Use cached resources or data: urls, but will similarly fall back to a | 922 // Use cached resources or data: urls, but will similarly fall back to a |
895 // deferred network load if we don't have the data available without a network | 923 // deferred network load if we don't have the data available without a network |
896 // request. We check allowImage() here, which is affected by m_imagesEnabled | 924 // request. We check allowImage() here, which is affected by m_imagesEnabled |
897 // but not m_autoLoadImages, in order to allow for this differing behavior. | 925 // but not m_autoLoadImages, in order to allow for this differing behavior. |
898 // | 926 // |
899 // TODO(japhet): Can we get rid of one of these settings? | 927 // TODO(japhet): Can we get rid of one of these settings? |
900 if (existing_resource->IsImage() && | 928 if (existing_resource->IsImage() && |
901 !Context().AllowImage(images_enabled_, existing_resource->Url())) { | 929 !Context().AllowImage(images_enabled_, existing_resource->Url())) { |
902 return kReload; | 930 return false; |
903 } | 931 } |
904 | 932 |
905 // Never use cache entries for downloadToFile / useStreamOnResponse requests. | 933 // Never use cache entries for downloadToFile / useStreamOnResponse requests. |
906 // The data will be delivered through other paths. | 934 // The data will be delivered through other paths. |
907 if (request.DownloadToFile() || request.UseStreamOnResponse()) | 935 if (request.DownloadToFile() || request.UseStreamOnResponse()) |
908 return kReload; | 936 return false; |
909 | 937 |
910 // Never reuse opaque responses from a service worker for requests that are | 938 // Never reuse opaque responses from a service worker for requests that are |
911 // not no-cors. https://crbug.com/625575 | 939 // not no-cors. https://crbug.com/625575 |
912 if (existing_resource->GetResponse().WasFetchedViaServiceWorker() && | 940 if (existing_resource->GetResponse().WasFetchedViaServiceWorker() && |
913 existing_resource->GetResponse().ServiceWorkerResponseType() == | 941 existing_resource->GetResponse().ServiceWorkerResponseType() == |
914 kWebServiceWorkerResponseTypeOpaque && | 942 kWebServiceWorkerResponseTypeOpaque && |
915 request.GetFetchRequestMode() != WebURLRequest::kFetchRequestModeNoCORS) { | 943 request.GetFetchRequestMode() != WebURLRequest::kFetchRequestModeNoCORS) { |
916 return kReload; | 944 return false; |
917 } | 945 } |
918 | 946 |
919 if (!is_static_data && !existing_resource->CanReuse(fetch_params)) | 947 if (!is_static_data && !existing_resource->CanReuse(params)) |
920 return kReload; | 948 return false; |
921 | 949 |
922 // Certain requests (e.g., XHRs) might have manually set headers that require | 950 // Certain requests (e.g., XHRs) might have manually set headers that require |
923 // revalidation. In theory, this should be a Revalidate case. In practice, the | 951 // revalidation. In theory, this should be a Revalidate case. In practice, the |
924 // MemoryCache revalidation path assumes a whole bunch of things about how | 952 // MemoryCache revalidation path assumes a whole bunch of things about how |
925 // revalidation works that manual headers violate, so punt to Reload instead. | 953 // revalidation works that manual headers violate, so punt to Reload instead. |
926 // | 954 // |
927 // Similarly, a request with manually added revalidation headers can lead to a | 955 // Similarly, a request with manually added revalidation headers can lead to a |
928 // 304 response for a request that wasn't flagged as a revalidation attempt. | 956 // 304 response for a request that wasn't flagged as a revalidation attempt. |
929 // Normally, successful revalidation will maintain the original response's | 957 // Normally, successful revalidation will maintain the original response's |
930 // status code, but for a manual revalidation the response code remains 304. | 958 // status code, but for a manual revalidation the response code remains 304. |
931 // In this case, the Resource likely has insufficient context to provide a | 959 // In this case, the Resource likely has insufficient context to provide a |
932 // useful cache hit or revalidation. See http://crbug.com/643659 | 960 // useful cache hit or revalidation. See http://crbug.com/643659 |
933 if (!is_static_data && | 961 if (!is_static_data && |
934 (request.IsConditional() || | 962 (request.IsConditional() || |
935 existing_resource->GetResponse().HttpStatusCode() == 304)) { | 963 existing_resource->GetResponse().HttpStatusCode() == 304)) { |
| 964 return false; |
| 965 } |
| 966 |
| 967 if (!is_static_data && |
| 968 !params.Options().CanReuseRequest(existing_resource->Options())) { |
| 969 return false; |
| 970 } |
| 971 |
| 972 return true; |
| 973 } |
| 974 |
| 975 ResourceFetcher::RevalidationPolicy |
| 976 ResourceFetcher::DetermineRevalidationPolicy( |
| 977 Resource::Type type, |
| 978 const FetchParameters& fetch_params, |
| 979 Resource* existing_resource, |
| 980 bool is_static_data) const { |
| 981 const ResourceRequest& request = fetch_params.GetResourceRequest(); |
| 982 |
| 983 if (!existing_resource) |
| 984 return kLoad; |
| 985 |
| 986 // If the existing resource is loading and the associated fetcher is not equal |
| 987 // to |this|, we must not use the resource. Otherwise, CSP violation may |
| 988 // happen in redirect handling. |
| 989 if (existing_resource->Loader() && |
| 990 existing_resource->Loader()->Fetcher() != this) { |
936 return kReload; | 991 return kReload; |
937 } | 992 } |
938 | 993 |
939 if (!is_static_data && | 994 // Checks if the resource has an explicit policy about integrity metadata. |
940 !fetch_params.Options().CanReuseRequest(existing_resource->Options())) { | 995 // |
| 996 // This is necessary because ScriptResource and CSSStyleSheetResource objects |
| 997 // do not keep the raw data around after the source is accessed once, so if |
| 998 // the resource is accessed from the MemoryCache for a second time, there is |
| 999 // no way to redo an integrity check. |
| 1000 // |
| 1001 // Thus, Blink implements a scheme where it caches the integrity information |
| 1002 // for those resources after the first time it is checked, and if there is |
| 1003 // another request for that resource, with the same integrity metadata, Blink |
| 1004 // skips the integrity calculation. However, if the integrity metadata is a |
| 1005 // mismatch, the MemoryCache must be skipped here, and a new request for the |
| 1006 // resource must be made to get the raw data. This is expected to be an |
| 1007 // uncommon case, however, as it implies two same-origin requests to the same |
| 1008 // resource, but with different integrity metadata. |
| 1009 RecordSriResourceIntegrityMismatchEvent(kCheckingForIntegrityMismatch); |
| 1010 if (existing_resource->MustRefetchDueToIntegrityMetadata(fetch_params)) { |
| 1011 RecordSriResourceIntegrityMismatchEvent(kRefetchDueToIntegrityMismatch); |
941 return kReload; | 1012 return kReload; |
942 } | 1013 } |
943 | 1014 |
944 // Always use preloads. | 1015 // If the same URL has been loaded as a different type, we need to reload. |
945 if (existing_resource->IsPreloaded()) | 1016 if (existing_resource->GetType() != type) { |
946 return kUse; | 1017 // FIXME: If existingResource is a Preload and the new type is LinkPrefetch |
| 1018 // We really should discard the new prefetch since the preload has more |
| 1019 // specific type information! crbug.com/379893 |
| 1020 // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case. |
| 1021 RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy " |
| 1022 "reloading due to type mismatch."; |
| 1023 return kReload; |
| 1024 } |
| 1025 |
| 1026 // If |existing_resource| is not reusable as a preloaded resource, it should |
| 1027 // not be reusable as a normal resource as well. |
| 1028 if (!IsReusableAlsoForPreloading(fetch_params, existing_resource, |
| 1029 is_static_data)) { |
| 1030 return kReload; |
| 1031 } |
947 | 1032 |
948 // If resource was populated from a SubstituteData load or data: url, use it. | 1033 // If resource was populated from a SubstituteData load or data: url, use it. |
949 if (is_static_data) | 1034 if (is_static_data) |
950 return kUse; | 1035 return kUse; |
951 | 1036 |
952 // Don't reload resources while pasting. | 1037 // Don't reload resources while pasting. |
953 if (allow_stale_resources_) | 1038 if (allow_stale_resources_) |
954 return kUse; | 1039 return kUse; |
955 | 1040 |
956 // WebCachePolicy::ReturnCacheDataElseLoad uses the cache no matter what. | 1041 // WebCachePolicy::ReturnCacheDataElseLoad uses the cache no matter what. |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1097 } | 1182 } |
1098 | 1183 |
1099 int ResourceFetcher::BlockingRequestCount() const { | 1184 int ResourceFetcher::BlockingRequestCount() const { |
1100 return loaders_.size(); | 1185 return loaders_.size(); |
1101 } | 1186 } |
1102 | 1187 |
1103 int ResourceFetcher::NonblockingRequestCount() const { | 1188 int ResourceFetcher::NonblockingRequestCount() const { |
1104 return non_blocking_loaders_.size(); | 1189 return non_blocking_loaders_.size(); |
1105 } | 1190 } |
1106 | 1191 |
1107 void ResourceFetcher::PreloadStarted(Resource* resource) { | |
1108 if (preloads_.Contains(resource)) | |
1109 return; | |
1110 resource->IncreasePreloadCount(); | |
1111 | |
1112 preloads_.insert(resource); | |
1113 | |
1114 if (preloaded_urls_for_test_) | |
1115 preloaded_urls_for_test_->insert(resource->Url().GetString()); | |
1116 } | |
1117 | |
1118 void ResourceFetcher::EnableIsPreloadedForTest() { | 1192 void ResourceFetcher::EnableIsPreloadedForTest() { |
1119 if (preloaded_urls_for_test_) | 1193 if (preloaded_urls_for_test_) |
1120 return; | 1194 return; |
1121 preloaded_urls_for_test_ = WTF::WrapUnique(new HashSet<String>); | 1195 preloaded_urls_for_test_ = WTF::WrapUnique(new HashSet<String>); |
1122 | 1196 |
1123 for (const auto& resource : preloads_) | 1197 for (const auto& pair : preloads_) { |
| 1198 Resource* resource = pair.value; |
1124 preloaded_urls_for_test_->insert(resource->Url().GetString()); | 1199 preloaded_urls_for_test_->insert(resource->Url().GetString()); |
| 1200 } |
1125 } | 1201 } |
1126 | 1202 |
1127 bool ResourceFetcher::IsPreloadedForTest(const KURL& url) const { | 1203 bool ResourceFetcher::IsPreloadedForTest(const KURL& url) const { |
1128 DCHECK(preloaded_urls_for_test_); | 1204 DCHECK(preloaded_urls_for_test_); |
1129 return preloaded_urls_for_test_->Contains(url.GetString()); | 1205 return preloaded_urls_for_test_->Contains(url.GetString()); |
1130 } | 1206 } |
1131 | 1207 |
1132 void ResourceFetcher::ClearPreloads(ClearPreloadsPolicy policy) { | 1208 void ResourceFetcher::ClearPreloads(ClearPreloadsPolicy policy) { |
1133 LogPreloadStats(policy); | 1209 LogPreloadStats(policy); |
1134 | 1210 |
1135 for (const auto& resource : preloads_) { | 1211 Vector<PreloadKey> keys_to_be_removed; |
| 1212 for (const auto& pair : preloads_) { |
| 1213 Resource* resource = pair.value; |
1136 if (policy == kClearAllPreloads || !resource->IsLinkPreload()) { | 1214 if (policy == kClearAllPreloads || !resource->IsLinkPreload()) { |
1137 resource->DecreasePreloadCount(); | 1215 resource->DecreasePreloadCount(); |
1138 if (resource->GetPreloadResult() == Resource::kPreloadNotReferenced) | 1216 if (resource->GetPreloadResult() == Resource::kPreloadNotReferenced) |
1139 GetMemoryCache()->Remove(resource.Get()); | 1217 GetMemoryCache()->Remove(resource); |
1140 preloads_.erase(resource); | 1218 keys_to_be_removed.push_back(pair.key); |
1141 } | 1219 } |
1142 } | 1220 } |
| 1221 preloads_.RemoveAll(keys_to_be_removed); |
| 1222 |
| 1223 matched_preloads_.clear(); |
1143 } | 1224 } |
1144 | 1225 |
1145 void ResourceFetcher::WarnUnusedPreloads() { | 1226 void ResourceFetcher::WarnUnusedPreloads() { |
1146 for (const auto& resource : preloads_) { | 1227 for (const auto& pair : preloads_) { |
| 1228 Resource* resource = pair.value; |
1147 if (resource && resource->IsLinkPreload() && | 1229 if (resource && resource->IsLinkPreload() && |
1148 resource->GetPreloadResult() == Resource::kPreloadNotReferenced) { | 1230 resource->GetPreloadResult() == Resource::kPreloadNotReferenced) { |
1149 Context().AddConsoleMessage( | 1231 Context().AddConsoleMessage( |
1150 "The resource " + resource->Url().GetString() + | 1232 "The resource " + resource->Url().GetString() + |
1151 " was preloaded using link preload but not used within a few " | 1233 " was preloaded using link preload but not used within a few " |
1152 "seconds from the window's load event. Please make sure it " | 1234 "seconds from the window's load event. Please make sure it " |
1153 "wasn't preloaded for nothing.", | 1235 "wasn't preloaded for nothing.", |
1154 FetchContext::kLogWarningMessage); | 1236 FetchContext::kLogWarningMessage); |
1155 } | 1237 } |
1156 } | 1238 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 | 1325 |
1244 resource_timing_info_map_.Take(resource); | 1326 resource_timing_info_map_.Take(resource); |
1245 | 1327 |
1246 bool is_internal_request = resource->Options().initiator_info.name == | 1328 bool is_internal_request = resource->Options().initiator_info.name == |
1247 FetchInitiatorTypeNames::internal; | 1329 FetchInitiatorTypeNames::internal; |
1248 | 1330 |
1249 Context().DispatchDidFail(resource->Identifier(), error, | 1331 Context().DispatchDidFail(resource->Identifier(), error, |
1250 resource->GetResponse().EncodedDataLength(), | 1332 resource->GetResponse().EncodedDataLength(), |
1251 is_internal_request); | 1333 is_internal_request); |
1252 | 1334 |
| 1335 if (error.IsCancellation()) |
| 1336 RemovePreload(resource); |
1253 resource->FinishAsError(error); | 1337 resource->FinishAsError(error); |
1254 | 1338 |
1255 HandleLoadCompletion(resource); | 1339 HandleLoadCompletion(resource); |
1256 } | 1340 } |
1257 | 1341 |
1258 void ResourceFetcher::MoveResourceLoaderToNonBlocking(ResourceLoader* loader) { | 1342 void ResourceFetcher::MoveResourceLoaderToNonBlocking(ResourceLoader* loader) { |
1259 DCHECK(loader); | 1343 DCHECK(loader); |
1260 // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in. | 1344 // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in. |
1261 CHECK(loaders_.Contains(loader)); | 1345 CHECK(loaders_.Contains(loader)); |
1262 non_blocking_loaders_.insert(loader); | 1346 non_blocking_loaders_.insert(loader); |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1402 unsigned fonts = 0; | 1486 unsigned fonts = 0; |
1403 unsigned font_misses = 0; | 1487 unsigned font_misses = 0; |
1404 unsigned medias = 0; | 1488 unsigned medias = 0; |
1405 unsigned media_misses = 0; | 1489 unsigned media_misses = 0; |
1406 unsigned text_tracks = 0; | 1490 unsigned text_tracks = 0; |
1407 unsigned text_track_misses = 0; | 1491 unsigned text_track_misses = 0; |
1408 unsigned imports = 0; | 1492 unsigned imports = 0; |
1409 unsigned import_misses = 0; | 1493 unsigned import_misses = 0; |
1410 unsigned raws = 0; | 1494 unsigned raws = 0; |
1411 unsigned raw_misses = 0; | 1495 unsigned raw_misses = 0; |
1412 for (const auto& resource : preloads_) { | 1496 for (const auto& pair : preloads_) { |
| 1497 Resource* resource = pair.value; |
1413 // Do not double count link rel preloads. These do not get cleared if the | 1498 // Do not double count link rel preloads. These do not get cleared if the |
1414 // ClearPreloadsPolicy is only clearing speculative markup preloads. | 1499 // ClearPreloadsPolicy is only clearing speculative markup preloads. |
1415 if (resource->IsLinkPreload() && | 1500 if (resource->IsLinkPreload() && |
1416 policy == kClearSpeculativeMarkupPreloads) { | 1501 policy == kClearSpeculativeMarkupPreloads) { |
1417 continue; | 1502 continue; |
1418 } | 1503 } |
1419 int miss_count = | 1504 int miss_count = |
1420 resource->GetPreloadResult() == Resource::kPreloadNotReferenced ? 1 : 0; | 1505 resource->GetPreloadResult() == Resource::kPreloadNotReferenced ? 1 : 0; |
1421 switch (resource->GetType()) { | 1506 switch (resource->GetType()) { |
1422 case Resource::kImage: | 1507 case Resource::kImage: |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1556 RequestLoadStarted(resource->Identifier(), resource, params, kUse); | 1641 RequestLoadStarted(resource->Identifier(), resource, params, kUse); |
1557 } | 1642 } |
1558 | 1643 |
1559 DEFINE_TRACE(ResourceFetcher) { | 1644 DEFINE_TRACE(ResourceFetcher) { |
1560 visitor->Trace(context_); | 1645 visitor->Trace(context_); |
1561 visitor->Trace(archive_); | 1646 visitor->Trace(archive_); |
1562 visitor->Trace(loaders_); | 1647 visitor->Trace(loaders_); |
1563 visitor->Trace(non_blocking_loaders_); | 1648 visitor->Trace(non_blocking_loaders_); |
1564 visitor->Trace(document_resources_); | 1649 visitor->Trace(document_resources_); |
1565 visitor->Trace(preloads_); | 1650 visitor->Trace(preloads_); |
| 1651 visitor->Trace(matched_preloads_); |
1566 visitor->Trace(resource_timing_info_map_); | 1652 visitor->Trace(resource_timing_info_map_); |
1567 } | 1653 } |
1568 | 1654 |
1569 } // namespace blink | 1655 } // namespace blink |
OLD | NEW |