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 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 } |
| 622 RevalidationPolicy policy = kLoad; | |
| 623 bool preload_found = false; | |
| 607 if (!resource) { | 624 if (!resource) { |
| 608 resource = | 625 resource = MatchPreload(params, factory.GetType()); |
| 609 GetMemoryCache()->ResourceForURL(params.Url(), GetCacheIdentifier()); | 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) { | |
| 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 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 762 resource->SetLinkPreload(params.IsLinkPreload()); | 794 resource->SetLinkPreload(params.IsLinkPreload()); |
| 763 if (params.IsSpeculativePreload()) { | 795 if (params.IsSpeculativePreload()) { |
| 764 resource->SetPreloadDiscoveryTime(params.PreloadDiscoveryTime()); | 796 resource->SetPreloadDiscoveryTime(params.PreloadDiscoveryTime()); |
| 765 } | 797 } |
| 766 resource->SetCacheIdentifier(cache_identifier); | 798 resource->SetCacheIdentifier(cache_identifier); |
| 767 | 799 |
| 768 // - Don't add main resource to cache to prevent reuse. | 800 // - Don't add main resource to cache to prevent reuse. |
| 769 // - Don't add the resource if its body will not be stored. | 801 // - Don't add the resource if its body will not be stored. |
| 770 if (factory.GetType() != Resource::kMainResource && | 802 if (factory.GetType() != Resource::kMainResource && |
| 771 params.Options().data_buffering_policy != kDoNotBufferData) { | 803 params.Options().data_buffering_policy != kDoNotBufferData) { |
| 772 GetMemoryCache()->Add(resource); | 804 GetMemoryCache()->Add(resource); |
|
Yoav Weiss
2017/05/12 16:53:46
Won't this add preloaded resources also to the mem
yhirano
2017/05/16 11:19:24
Yes, this CL changes how to match preloads, and do
| |
| 773 } | 805 } |
| 774 return resource; | 806 return resource; |
| 775 } | 807 } |
| 776 | 808 |
| 777 void ResourceFetcher::StorePerformanceTimingInitiatorInformation( | 809 void ResourceFetcher::StorePerformanceTimingInitiatorInformation( |
| 778 Resource* resource) { | 810 Resource* resource) { |
| 779 const AtomicString& fetch_initiator = resource->Options().initiator_info.name; | 811 const AtomicString& fetch_initiator = resource->Options().initiator_info.name; |
| 780 if (fetch_initiator == FetchInitiatorTypeNames::internal) | 812 if (fetch_initiator == FetchInitiatorTypeNames::internal) |
| 781 return; | 813 return; |
| 782 | 814 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 820 if (it != resource_timing_info_map_.end()) { | 852 if (it != resource_timing_info_map_.end()) { |
| 821 it->value->AddRedirect(redirect_response, cross_origin); | 853 it->value->AddRedirect(redirect_response, cross_origin); |
| 822 } | 854 } |
| 823 | 855 |
| 824 if (resource->GetType() == Resource::kMainResource) { | 856 if (resource->GetType() == Resource::kMainResource) { |
| 825 DCHECK(navigation_timing_info_); | 857 DCHECK(navigation_timing_info_); |
| 826 navigation_timing_info_->AddRedirect(redirect_response, cross_origin); | 858 navigation_timing_info_->AddRedirect(redirect_response, cross_origin); |
| 827 } | 859 } |
| 828 } | 860 } |
| 829 | 861 |
| 830 ResourceFetcher::RevalidationPolicy | 862 Resource* ResourceFetcher::MatchPreload(const FetchParameters& params, |
| 831 ResourceFetcher::DetermineRevalidationPolicy( | 863 Resource::Type type) { |
| 832 Resource::Type type, | 864 auto it = preloads_.find(PreloadKey(params.Url(), type)); |
| 833 const FetchParameters& fetch_params, | 865 if (it == preloads_.end()) |
| 834 Resource* existing_resource, | 866 return nullptr; |
| 835 bool is_static_data) const { | |
| 836 const ResourceRequest& request = fetch_params.GetResourceRequest(); | |
| 837 | 867 |
| 838 if (!existing_resource) | 868 Resource* resource = it->value; |
| 839 return kLoad; | |
| 840 | 869 |
| 841 // If the existing resource is loading and the associated fetcher is not equal | 870 RecordSriResourceIntegrityMismatchEvent(kCheckingForIntegrityMismatch); |
| 842 // to |this|, we must not use the resource. Otherwise, CSP violation may | 871 if (resource->MustRefetchDueToIntegrityMetadata(params)) |
| 843 // happen in redirect handling. | 872 return nullptr; |
| 844 if (existing_resource->Loader() && | 873 |
| 845 existing_resource->Loader()->Fetcher() != this) { | 874 if (params.IsSpeculativePreload()) |
| 846 return kReload; | 875 return resource; |
| 876 if (params.IsLinkPreload()) { | |
| 877 resource->SetLinkPreload(true); | |
| 878 return resource; | |
| 847 } | 879 } |
| 848 | 880 |
| 849 // Checks if the resource has an explicit policy about integrity metadata. | 881 if (!IsReusableForPreloading(params, resource, false)) |
| 850 // | 882 return nullptr; |
| 851 // This is necessary because ScriptResource and CSSStyleSheetResource objects | 883 |
| 852 // do not keep the raw data around after the source is accessed once, so if | 884 resource->DecreasePreloadCount(); |
| 853 // the resource is accessed from the MemoryCache for a second time, there is | 885 preloads_.erase(it); |
| 854 // no way to redo an integrity check. | 886 matched_preloads_.push_back(resource); |
| 855 // | 887 return resource; |
| 856 // Thus, Blink implements a scheme where it caches the integrity information | 888 } |
| 857 // for those resources after the first time it is checked, and if there is | 889 |
| 858 // another request for that resource, with the same integrity metadata, Blink | 890 void ResourceFetcher::InsertAsPreloadIfNecessary(Resource* resource, |
| 859 // skips the integrity calculation. However, if the integrity metadata is a | 891 const FetchParameters& params, |
| 860 // mismatch, the MemoryCache must be skipped here, and a new request for the | 892 Resource::Type type) { |
| 861 // resource must be made to get the raw data. This is expected to be an | 893 if (!params.IsSpeculativePreload() && !params.IsLinkPreload()) |
| 862 // uncommon case, however, as it implies two same-origin requests to the same | 894 return; |
| 863 // resource, but with different integrity metadata. | 895 // CSP layout tests verify that preloads are subject to access checks by |
| 864 RecordSriResourceIntegrityMismatchEvent(kCheckingForIntegrityMismatch); | 896 // seeing if they are in the `preload started` list. Therefore do not add |
| 865 if (existing_resource->MustRefetchDueToIntegrityMetadata(fetch_params)) { | 897 // them to the list if the load is immediately denied. |
| 866 RecordSriResourceIntegrityMismatchEvent(kRefetchDueToIntegrityMismatch); | 898 if (resource->GetResourceError().IsAccessCheck()) |
| 867 return kReload; | 899 return; |
| 900 PreloadKey key(params.Url(), type); | |
| 901 if (preloads_.find(key) == preloads_.end()) { | |
| 902 preloads_.insert(key, resource); | |
| 903 resource->IncreasePreloadCount(); | |
| 904 if (preloaded_urls_for_test_) | |
| 905 preloaded_urls_for_test_->insert(resource->Url().GetString()); | |
| 868 } | 906 } |
| 907 } | |
| 869 | 908 |
| 870 // If the same URL has been loaded as a different type, we need to reload. | 909 bool ResourceFetcher::IsReusableForPreloading(const FetchParameters& params, |
| 871 if (existing_resource->GetType() != type) { | 910 Resource* existing_resource, |
| 872 // FIXME: If existingResource is a Preload and the new type is LinkPrefetch | 911 bool is_static_data) const { |
| 873 // We really should discard the new prefetch since the preload has more | 912 const ResourceRequest& request = params.GetResourceRequest(); |
| 874 // specific type information! crbug.com/379893 | |
| 875 // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case. | |
| 876 RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy " | |
| 877 "reloading due to type mismatch."; | |
| 878 return kReload; | |
| 879 } | |
| 880 | |
| 881 // We already have a preload going for this URL. | |
| 882 if (fetch_params.IsSpeculativePreload() && existing_resource->IsPreloaded()) | |
| 883 return kUse; | |
| 884 | |
| 885 // Do not load from cache if images are not enabled. There are two general | 913 // Do not load from cache if images are not enabled. There are two general |
| 886 // cases: | 914 // cases: |
| 887 // | 915 // |
| 888 // 1. Images are disabled. Don't ever load images, even if the image is cached | 916 // 1. Images are disabled. Don't ever load images, even if the image is cached |
| 889 // or it is a data: url. In this case, we "Reload" the image, then defer it | 917 // or it is a data: url. In this case, we "Reload" the image, then defer it |
| 890 // with resourceNeedsLoad() so that it never actually goes to the network. | 918 // with resourceNeedsLoad() so that it never actually goes to the network. |
| 891 // | 919 // |
| 892 // 2. Images are enabled, but not loaded automatically. In this case, we will | 920 // 2. Images are enabled, but not loaded automatically. In this case, we will |
| 893 // Use cached resources or data: urls, but will similarly fall back to a | 921 // Use cached resources or data: urls, but will similarly fall back to a |
| 894 // deferred network load if we don't have the data available without a network | 922 // deferred network load if we don't have the data available without a network |
| 895 // request. We check allowImage() here, which is affected by m_imagesEnabled | 923 // request. We check allowImage() here, which is affected by m_imagesEnabled |
| 896 // but not m_autoLoadImages, in order to allow for this differing behavior. | 924 // but not m_autoLoadImages, in order to allow for this differing behavior. |
| 897 // | 925 // |
| 898 // TODO(japhet): Can we get rid of one of these settings? | 926 // TODO(japhet): Can we get rid of one of these settings? |
| 899 if (existing_resource->IsImage() && | 927 if (existing_resource->IsImage() && |
| 900 !Context().AllowImage(images_enabled_, existing_resource->Url())) { | 928 !Context().AllowImage(images_enabled_, existing_resource->Url())) { |
| 901 return kReload; | 929 return false; |
| 902 } | 930 } |
| 903 | 931 |
| 904 // Never use cache entries for downloadToFile / useStreamOnResponse requests. | 932 // Never use cache entries for downloadToFile / useStreamOnResponse requests. |
| 905 // The data will be delivered through other paths. | 933 // The data will be delivered through other paths. |
| 906 if (request.DownloadToFile() || request.UseStreamOnResponse()) | 934 if (request.DownloadToFile() || request.UseStreamOnResponse()) |
| 907 return kReload; | 935 return false; |
| 908 | 936 |
| 909 // Never reuse opaque responses from a service worker for requests that are | 937 // Never reuse opaque responses from a service worker for requests that are |
| 910 // not no-cors. https://crbug.com/625575 | 938 // not no-cors. https://crbug.com/625575 |
| 911 if (existing_resource->GetResponse().WasFetchedViaServiceWorker() && | 939 if (existing_resource->GetResponse().WasFetchedViaServiceWorker() && |
| 912 existing_resource->GetResponse().ServiceWorkerResponseType() == | 940 existing_resource->GetResponse().ServiceWorkerResponseType() == |
| 913 kWebServiceWorkerResponseTypeOpaque && | 941 kWebServiceWorkerResponseTypeOpaque && |
| 914 request.GetFetchRequestMode() != WebURLRequest::kFetchRequestModeNoCORS) { | 942 request.GetFetchRequestMode() != WebURLRequest::kFetchRequestModeNoCORS) { |
| 915 return kReload; | 943 return false; |
| 916 } | 944 } |
| 917 | 945 |
| 918 if (!is_static_data && !existing_resource->CanReuse(fetch_params)) | 946 if (!is_static_data && !existing_resource->CanReuse(params)) |
| 919 return kReload; | 947 return false; |
| 920 | 948 |
| 921 // Certain requests (e.g., XHRs) might have manually set headers that require | 949 // Certain requests (e.g., XHRs) might have manually set headers that require |
| 922 // revalidation. In theory, this should be a Revalidate case. In practice, the | 950 // revalidation. In theory, this should be a Revalidate case. In practice, the |
| 923 // MemoryCache revalidation path assumes a whole bunch of things about how | 951 // MemoryCache revalidation path assumes a whole bunch of things about how |
| 924 // revalidation works that manual headers violate, so punt to Reload instead. | 952 // revalidation works that manual headers violate, so punt to Reload instead. |
| 925 // | 953 // |
| 926 // Similarly, a request with manually added revalidation headers can lead to a | 954 // Similarly, a request with manually added revalidation headers can lead to a |
| 927 // 304 response for a request that wasn't flagged as a revalidation attempt. | 955 // 304 response for a request that wasn't flagged as a revalidation attempt. |
| 928 // Normally, successful revalidation will maintain the original response's | 956 // Normally, successful revalidation will maintain the original response's |
| 929 // status code, but for a manual revalidation the response code remains 304. | 957 // status code, but for a manual revalidation the response code remains 304. |
| 930 // In this case, the Resource likely has insufficient context to provide a | 958 // In this case, the Resource likely has insufficient context to provide a |
| 931 // useful cache hit or revalidation. See http://crbug.com/643659 | 959 // useful cache hit or revalidation. See http://crbug.com/643659 |
| 932 if (!is_static_data && | 960 if (!is_static_data && |
| 933 (request.IsConditional() || | 961 (request.IsConditional() || |
| 934 existing_resource->GetResponse().HttpStatusCode() == 304)) { | 962 existing_resource->GetResponse().HttpStatusCode() == 304)) { |
| 963 return false; | |
| 964 } | |
| 965 | |
| 966 if (!is_static_data && | |
| 967 !params.Options().CanReuseRequest(existing_resource->Options())) { | |
| 968 return false; | |
| 969 } | |
| 970 | |
| 971 return true; | |
| 972 } | |
| 973 | |
| 974 ResourceFetcher::RevalidationPolicy | |
| 975 ResourceFetcher::DetermineRevalidationPolicy( | |
| 976 Resource::Type type, | |
| 977 const FetchParameters& fetch_params, | |
| 978 Resource* existing_resource, | |
| 979 bool is_static_data) const { | |
| 980 const ResourceRequest& request = fetch_params.GetResourceRequest(); | |
| 981 | |
| 982 if (!existing_resource) | |
| 983 return kLoad; | |
| 984 | |
| 985 // If the existing resource is loading and the associated fetcher is not equal | |
| 986 // to |this|, we must not use the resource. Otherwise, CSP violation may | |
| 987 // happen in redirect handling. | |
| 988 if (existing_resource->Loader() && | |
| 989 existing_resource->Loader()->Fetcher() != this) { | |
| 935 return kReload; | 990 return kReload; |
| 936 } | 991 } |
| 937 | 992 |
| 938 if (!is_static_data && | 993 // Checks if the resource has an explicit policy about integrity metadata. |
| 939 !fetch_params.Options().CanReuseRequest(existing_resource->Options())) { | 994 // |
| 995 // This is necessary because ScriptResource and CSSStyleSheetResource objects | |
| 996 // do not keep the raw data around after the source is accessed once, so if | |
| 997 // the resource is accessed from the MemoryCache for a second time, there is | |
| 998 // no way to redo an integrity check. | |
| 999 // | |
| 1000 // Thus, Blink implements a scheme where it caches the integrity information | |
| 1001 // for those resources after the first time it is checked, and if there is | |
| 1002 // another request for that resource, with the same integrity metadata, Blink | |
| 1003 // skips the integrity calculation. However, if the integrity metadata is a | |
| 1004 // mismatch, the MemoryCache must be skipped here, and a new request for the | |
| 1005 // resource must be made to get the raw data. This is expected to be an | |
| 1006 // uncommon case, however, as it implies two same-origin requests to the same | |
| 1007 // resource, but with different integrity metadata. | |
| 1008 RecordSriResourceIntegrityMismatchEvent(kCheckingForIntegrityMismatch); | |
| 1009 if (existing_resource->MustRefetchDueToIntegrityMetadata(fetch_params)) { | |
| 1010 RecordSriResourceIntegrityMismatchEvent(kRefetchDueToIntegrityMismatch); | |
| 940 return kReload; | 1011 return kReload; |
| 941 } | 1012 } |
| 942 | 1013 |
| 943 // Always use preloads. | 1014 // If the same URL has been loaded as a different type, we need to reload. |
| 944 if (existing_resource->IsPreloaded()) | 1015 if (existing_resource->GetType() != type) { |
| 945 return kUse; | 1016 // FIXME: If existingResource is a Preload and the new type is LinkPrefetch |
| 1017 // We really should discard the new prefetch since the preload has more | |
| 1018 // specific type information! crbug.com/379893 | |
| 1019 // fast/dom/HTMLLinkElement/link-and-subresource-test hits this case. | |
| 1020 RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::determineRevalidationPolicy " | |
| 1021 "reloading due to type mismatch."; | |
| 1022 return kReload; | |
| 1023 } | |
| 1024 | |
| 1025 // If |existing_resource| is not reusable as a preloaded resource, it should | |
| 1026 // not be reusable as a normal resource as well. | |
| 1027 if (!IsReusableForPreloading(fetch_params, existing_resource, is_static_data)) | |
|
Yoav Weiss
2017/05/12 16:33:57
Can we maybe change the name of `isReusableForPrel
kinuko
2017/05/15 02:09:04
+1, felt slightly confusing.
yhirano
2017/05/16 11:19:24
I couldn't come up with a better name. Do you have
kinuko
2017/05/16 22:58:53
IsReusableAlsoForPreloading ...? (I'm not good at
yhirano
2017/05/17 04:24:44
Done.
| |
| 1028 return kReload; | |
| 946 | 1029 |
| 947 // If resource was populated from a SubstituteData load or data: url, use it. | 1030 // If resource was populated from a SubstituteData load or data: url, use it. |
| 948 if (is_static_data) | 1031 if (is_static_data) |
| 949 return kUse; | 1032 return kUse; |
| 950 | 1033 |
| 951 // Don't reload resources while pasting. | 1034 // Don't reload resources while pasting. |
| 952 if (allow_stale_resources_) | 1035 if (allow_stale_resources_) |
| 953 return kUse; | 1036 return kUse; |
| 954 | 1037 |
| 955 // WebCachePolicy::ReturnCacheDataElseLoad uses the cache no matter what. | 1038 // WebCachePolicy::ReturnCacheDataElseLoad uses the cache no matter what. |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1096 } | 1179 } |
| 1097 | 1180 |
| 1098 int ResourceFetcher::BlockingRequestCount() const { | 1181 int ResourceFetcher::BlockingRequestCount() const { |
| 1099 return loaders_.size(); | 1182 return loaders_.size(); |
| 1100 } | 1183 } |
| 1101 | 1184 |
| 1102 int ResourceFetcher::NonblockingRequestCount() const { | 1185 int ResourceFetcher::NonblockingRequestCount() const { |
| 1103 return non_blocking_loaders_.size(); | 1186 return non_blocking_loaders_.size(); |
| 1104 } | 1187 } |
| 1105 | 1188 |
| 1106 void ResourceFetcher::PreloadStarted(Resource* resource) { | |
| 1107 if (preloads_.Contains(resource)) | |
| 1108 return; | |
| 1109 resource->IncreasePreloadCount(); | |
| 1110 | |
| 1111 preloads_.insert(resource); | |
| 1112 | |
| 1113 if (preloaded_urls_for_test_) | |
| 1114 preloaded_urls_for_test_->insert(resource->Url().GetString()); | |
| 1115 } | |
| 1116 | |
| 1117 void ResourceFetcher::EnableIsPreloadedForTest() { | 1189 void ResourceFetcher::EnableIsPreloadedForTest() { |
| 1118 if (preloaded_urls_for_test_) | 1190 if (preloaded_urls_for_test_) |
| 1119 return; | 1191 return; |
| 1120 preloaded_urls_for_test_ = WTF::WrapUnique(new HashSet<String>); | 1192 preloaded_urls_for_test_ = WTF::WrapUnique(new HashSet<String>); |
| 1121 | 1193 |
| 1122 for (const auto& resource : preloads_) | 1194 for (const auto& pair : preloads_) { |
| 1195 Resource* resource = pair.value; | |
| 1123 preloaded_urls_for_test_->insert(resource->Url().GetString()); | 1196 preloaded_urls_for_test_->insert(resource->Url().GetString()); |
| 1197 } | |
| 1124 } | 1198 } |
| 1125 | 1199 |
| 1126 bool ResourceFetcher::IsPreloadedForTest(const KURL& url) const { | 1200 bool ResourceFetcher::IsPreloadedForTest(const KURL& url) const { |
| 1127 DCHECK(preloaded_urls_for_test_); | 1201 DCHECK(preloaded_urls_for_test_); |
| 1128 return preloaded_urls_for_test_->Contains(url.GetString()); | 1202 return preloaded_urls_for_test_->Contains(url.GetString()); |
| 1129 } | 1203 } |
| 1130 | 1204 |
| 1131 void ResourceFetcher::ClearPreloads(ClearPreloadsPolicy policy) { | 1205 void ResourceFetcher::ClearPreloads(ClearPreloadsPolicy policy) { |
| 1132 LogPreloadStats(policy); | 1206 LogPreloadStats(policy); |
| 1133 | 1207 |
| 1134 for (const auto& resource : preloads_) { | 1208 Vector<PreloadKey> keys_to_be_removed; |
| 1209 for (const auto& pair : preloads_) { | |
| 1210 Resource* resource = pair.value; | |
| 1135 if (policy == kClearAllPreloads || !resource->IsLinkPreload()) { | 1211 if (policy == kClearAllPreloads || !resource->IsLinkPreload()) { |
| 1136 resource->DecreasePreloadCount(); | 1212 resource->DecreasePreloadCount(); |
| 1137 if (resource->GetPreloadResult() == Resource::kPreloadNotReferenced) | 1213 if (resource->GetPreloadResult() == Resource::kPreloadNotReferenced) |
| 1138 GetMemoryCache()->Remove(resource.Get()); | 1214 GetMemoryCache()->Remove(resource); |
| 1139 preloads_.erase(resource); | 1215 keys_to_be_removed.push_back(pair.key); |
| 1140 } | 1216 } |
| 1141 } | 1217 } |
| 1218 preloads_.RemoveAll(keys_to_be_removed); | |
| 1219 | |
| 1220 matched_preloads_.clear(); | |
| 1142 } | 1221 } |
| 1143 | 1222 |
| 1144 void ResourceFetcher::WarnUnusedPreloads() { | 1223 void ResourceFetcher::WarnUnusedPreloads() { |
| 1145 for (const auto& resource : preloads_) { | 1224 for (const auto& pair : preloads_) { |
| 1225 Resource* resource = pair.value; | |
| 1146 if (resource && resource->IsLinkPreload() && | 1226 if (resource && resource->IsLinkPreload() && |
| 1147 resource->GetPreloadResult() == Resource::kPreloadNotReferenced) { | 1227 resource->GetPreloadResult() == Resource::kPreloadNotReferenced) { |
| 1148 Context().AddConsoleMessage( | 1228 Context().AddConsoleMessage( |
| 1149 "The resource " + resource->Url().GetString() + | 1229 "The resource " + resource->Url().GetString() + |
| 1150 " was preloaded using link preload but not used within a few " | 1230 " was preloaded using link preload but not used within a few " |
| 1151 "seconds from the window's load event. Please make sure it " | 1231 "seconds from the window's load event. Please make sure it " |
| 1152 "wasn't preloaded for nothing.", | 1232 "wasn't preloaded for nothing.", |
| 1153 FetchContext::kLogWarningMessage); | 1233 FetchContext::kLogWarningMessage); |
| 1154 } | 1234 } |
| 1155 } | 1235 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1242 | 1322 |
| 1243 resource_timing_info_map_.Take(resource); | 1323 resource_timing_info_map_.Take(resource); |
| 1244 | 1324 |
| 1245 bool is_internal_request = resource->Options().initiator_info.name == | 1325 bool is_internal_request = resource->Options().initiator_info.name == |
| 1246 FetchInitiatorTypeNames::internal; | 1326 FetchInitiatorTypeNames::internal; |
| 1247 | 1327 |
| 1248 Context().DispatchDidFail(resource->Identifier(), error, | 1328 Context().DispatchDidFail(resource->Identifier(), error, |
| 1249 resource->GetResponse().EncodedDataLength(), | 1329 resource->GetResponse().EncodedDataLength(), |
| 1250 is_internal_request); | 1330 is_internal_request); |
| 1251 | 1331 |
| 1332 if (error.IsCancellation()) | |
| 1333 RemovePreload(resource); | |
| 1252 resource->FinishAsError(error); | 1334 resource->FinishAsError(error); |
| 1253 | 1335 |
| 1254 HandleLoadCompletion(resource); | 1336 HandleLoadCompletion(resource); |
| 1255 } | 1337 } |
| 1256 | 1338 |
| 1257 void ResourceFetcher::MoveResourceLoaderToNonBlocking(ResourceLoader* loader) { | 1339 void ResourceFetcher::MoveResourceLoaderToNonBlocking(ResourceLoader* loader) { |
| 1258 DCHECK(loader); | 1340 DCHECK(loader); |
| 1259 // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in. | 1341 // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in. |
| 1260 CHECK(loaders_.Contains(loader)); | 1342 CHECK(loaders_.Contains(loader)); |
| 1261 non_blocking_loaders_.insert(loader); | 1343 non_blocking_loaders_.insert(loader); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1400 unsigned fonts = 0; | 1482 unsigned fonts = 0; |
| 1401 unsigned font_misses = 0; | 1483 unsigned font_misses = 0; |
| 1402 unsigned medias = 0; | 1484 unsigned medias = 0; |
| 1403 unsigned media_misses = 0; | 1485 unsigned media_misses = 0; |
| 1404 unsigned text_tracks = 0; | 1486 unsigned text_tracks = 0; |
| 1405 unsigned text_track_misses = 0; | 1487 unsigned text_track_misses = 0; |
| 1406 unsigned imports = 0; | 1488 unsigned imports = 0; |
| 1407 unsigned import_misses = 0; | 1489 unsigned import_misses = 0; |
| 1408 unsigned raws = 0; | 1490 unsigned raws = 0; |
| 1409 unsigned raw_misses = 0; | 1491 unsigned raw_misses = 0; |
| 1410 for (const auto& resource : preloads_) { | 1492 for (const auto& pair : preloads_) { |
| 1493 Resource* resource = pair.value; | |
| 1411 // Do not double count link rel preloads. These do not get cleared if the | 1494 // Do not double count link rel preloads. These do not get cleared if the |
| 1412 // ClearPreloadsPolicy is only clearing speculative markup preloads. | 1495 // ClearPreloadsPolicy is only clearing speculative markup preloads. |
| 1413 if (resource->IsLinkPreload() && | 1496 if (resource->IsLinkPreload() && |
| 1414 policy == kClearSpeculativeMarkupPreloads) { | 1497 policy == kClearSpeculativeMarkupPreloads) { |
| 1415 continue; | 1498 continue; |
| 1416 } | 1499 } |
| 1417 int miss_count = | 1500 int miss_count = |
| 1418 resource->GetPreloadResult() == Resource::kPreloadNotReferenced ? 1 : 0; | 1501 resource->GetPreloadResult() == Resource::kPreloadNotReferenced ? 1 : 0; |
| 1419 switch (resource->GetType()) { | 1502 switch (resource->GetType()) { |
| 1420 case Resource::kImage: | 1503 case Resource::kImage: |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1554 RequestLoadStarted(resource->Identifier(), resource, params, kUse); | 1637 RequestLoadStarted(resource->Identifier(), resource, params, kUse); |
| 1555 } | 1638 } |
| 1556 | 1639 |
| 1557 DEFINE_TRACE(ResourceFetcher) { | 1640 DEFINE_TRACE(ResourceFetcher) { |
| 1558 visitor->Trace(context_); | 1641 visitor->Trace(context_); |
| 1559 visitor->Trace(archive_); | 1642 visitor->Trace(archive_); |
| 1560 visitor->Trace(loaders_); | 1643 visitor->Trace(loaders_); |
| 1561 visitor->Trace(non_blocking_loaders_); | 1644 visitor->Trace(non_blocking_loaders_); |
| 1562 visitor->Trace(document_resources_); | 1645 visitor->Trace(document_resources_); |
| 1563 visitor->Trace(preloads_); | 1646 visitor->Trace(preloads_); |
| 1647 visitor->Trace(matched_preloads_); | |
| 1564 visitor->Trace(resource_timing_info_map_); | 1648 visitor->Trace(resource_timing_info_map_); |
| 1565 } | 1649 } |
| 1566 | 1650 |
| 1567 } // namespace blink | 1651 } // namespace blink |
| OLD | NEW |