OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/predictors/resource_prefetch_predictor.h" | 5 #include "chrome/browser/predictors/resource_prefetch_predictor.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 void InitializeOriginStatFromOriginRequestSummary( | 93 void InitializeOriginStatFromOriginRequestSummary( |
94 OriginStat* origin, | 94 OriginStat* origin, |
95 const ResourcePrefetchPredictor::OriginRequestSummary& summary) { | 95 const ResourcePrefetchPredictor::OriginRequestSummary& summary) { |
96 origin->set_origin(summary.origin.spec()); | 96 origin->set_origin(summary.origin.spec()); |
97 origin->set_number_of_hits(1); | 97 origin->set_number_of_hits(1); |
98 origin->set_average_position(summary.first_occurrence + 1); | 98 origin->set_average_position(summary.first_occurrence + 1); |
99 origin->set_always_access_network(summary.always_access_network); | 99 origin->set_always_access_network(summary.always_access_network); |
100 origin->set_accessed_network(summary.accessed_network); | 100 origin->set_accessed_network(summary.accessed_network); |
101 } | 101 } |
102 | 102 |
| 103 bool IsManifestTooOld(const precache::PrecacheManifest& manifest) { |
| 104 const base::TimeDelta kMaxManifestAge = base::TimeDelta::FromDays(5); |
| 105 return base::Time::Now() - base::Time::FromDoubleT(manifest.id().id()) > |
| 106 kMaxManifestAge; |
| 107 } |
| 108 |
103 // Used to fetch the visit count for a URL from the History database. | 109 // Used to fetch the visit count for a URL from the History database. |
104 class GetUrlVisitCountTask : public history::HistoryDBTask { | 110 class GetUrlVisitCountTask : public history::HistoryDBTask { |
105 public: | 111 public: |
106 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; | 112 using URLRequestSummary = ResourcePrefetchPredictor::URLRequestSummary; |
107 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; | 113 using PageRequestSummary = ResourcePrefetchPredictor::PageRequestSummary; |
108 typedef base::Callback<void(size_t, // URL visit count. | 114 typedef base::Callback<void(size_t, // URL visit count. |
109 const PageRequestSummary&)> | 115 const PageRequestSummary&)> |
110 VisitInfoCallback; | 116 VisitInfoCallback; |
111 | 117 |
112 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary, | 118 GetUrlVisitCountTask(std::unique_ptr<PageRequestSummary> summary, |
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
891 prediction->is_host = false; | 897 prediction->is_host = false; |
892 prediction->main_frame_key = redirect_endpoint; | 898 prediction->main_frame_key = redirect_endpoint; |
893 prediction->is_redirected = (redirect_endpoint != main_frame_url_spec); | 899 prediction->is_redirected = (redirect_endpoint != main_frame_url_spec); |
894 } | 900 } |
895 return true; | 901 return true; |
896 } | 902 } |
897 | 903 |
898 // Use host data if the URL-based prediction isn't available. | 904 // Use host data if the URL-based prediction isn't available. |
899 std::string main_frame_url_host = main_frame_url.host(); | 905 std::string main_frame_url_host = main_frame_url.host(); |
900 if (GetRedirectEndpoint(main_frame_url_host, *host_redirect_table_cache_, | 906 if (GetRedirectEndpoint(main_frame_url_host, *host_redirect_table_cache_, |
901 &redirect_endpoint) && | 907 &redirect_endpoint)) { |
902 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { | 908 if (PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, |
903 if (prediction) { | 909 urls)) { |
904 prediction->is_host = true; | 910 if (prediction) { |
905 prediction->main_frame_key = redirect_endpoint; | 911 prediction->is_host = true; |
906 prediction->is_redirected = (redirect_endpoint != main_frame_url_host); | 912 prediction->main_frame_key = redirect_endpoint; |
| 913 prediction->is_redirected = (redirect_endpoint != main_frame_url_host); |
| 914 } |
| 915 return true; |
907 } | 916 } |
908 return true; | 917 |
| 918 if (config_.is_manifests_enabled) { |
| 919 // Use manifest data for host if available. |
| 920 std::string manifest_host = redirect_endpoint; |
| 921 if (base::StartsWith(manifest_host, "www.", base::CompareCase::SENSITIVE)) |
| 922 manifest_host.assign(manifest_host, 4, std::string::npos); |
| 923 if (PopulateFromManifest(manifest_host, urls)) { |
| 924 if (prediction) { |
| 925 prediction->is_host = true; |
| 926 prediction->main_frame_key = redirect_endpoint; |
| 927 prediction->is_redirected = |
| 928 (redirect_endpoint != main_frame_url_host); |
| 929 } |
| 930 return true; |
| 931 } |
| 932 } |
909 } | 933 } |
910 | |
911 return false; | 934 return false; |
912 } | 935 } |
913 | 936 |
914 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( | 937 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( |
915 const std::string& main_frame_key, | 938 const std::string& main_frame_key, |
916 const PrefetchDataMap& data_map, | 939 const PrefetchDataMap& data_map, |
917 std::vector<GURL>* urls) const { | 940 std::vector<GURL>* urls) const { |
918 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); | 941 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); |
919 if (it == data_map.end()) | 942 if (it == data_map.end()) |
920 return false; | 943 return false; |
921 | 944 |
922 bool has_prefetchable_resource = false; | 945 bool has_prefetchable_resource = false; |
923 for (const ResourceData& resource : it->second.resources()) { | 946 for (const ResourceData& resource : it->second.resources()) { |
924 if (IsResourcePrefetchable(resource)) { | 947 if (IsResourcePrefetchable(resource)) { |
925 has_prefetchable_resource = true; | 948 has_prefetchable_resource = true; |
926 if (urls) | 949 if (urls) |
927 urls->push_back(GURL(resource.resource_url())); | 950 urls->push_back(GURL(resource.resource_url())); |
928 } | 951 } |
929 } | 952 } |
930 | 953 |
931 return has_prefetchable_resource; | 954 return has_prefetchable_resource; |
932 } | 955 } |
933 | 956 |
| 957 bool ResourcePrefetchPredictor::PopulateFromManifest( |
| 958 const std::string& manifest_host, |
| 959 std::vector<GURL>* urls) const { |
| 960 auto it = manifest_table_cache_->find(manifest_host); |
| 961 if (it == manifest_table_cache_->end()) |
| 962 return false; |
| 963 |
| 964 const precache::PrecacheManifest& manifest = it->second; |
| 965 |
| 966 if (IsManifestTooOld(manifest)) |
| 967 return false; |
| 968 |
| 969 const float kMinWeight = 0.7f; |
| 970 |
| 971 // Don't prefetch resource if it has false bit in any of the following |
| 972 // bitsets. All bits assumed to be true if an optional has no value. |
| 973 base::Optional<std::vector<bool>> not_unused = |
| 974 precache::GetResourceBitset(manifest, internal::kUnusedRemovedExperiment); |
| 975 base::Optional<std::vector<bool>> not_versioned = precache::GetResourceBitset( |
| 976 manifest, internal::kVersionedRemovedExperiment); |
| 977 base::Optional<std::vector<bool>> not_no_store = precache::GetResourceBitset( |
| 978 manifest, internal::kNoStoreRemovedExperiment); |
| 979 |
| 980 bool has_prefetchable_resource = false; |
| 981 for (int i = 0; i < manifest.resource_size(); ++i) { |
| 982 const precache::PrecacheResource& resource = manifest.resource(i); |
| 983 if (resource.weight_ratio() > kMinWeight && |
| 984 (!not_unused.has_value() || not_unused.value()[i]) && |
| 985 (!not_versioned.has_value() || not_versioned.value()[i]) && |
| 986 (!not_no_store.has_value() || not_no_store.value()[i])) { |
| 987 has_prefetchable_resource = true; |
| 988 if (urls) |
| 989 urls->emplace_back(resource.url()); |
| 990 } |
| 991 } |
| 992 |
| 993 return has_prefetchable_resource; |
| 994 } |
| 995 |
934 void ResourcePrefetchPredictor::CreateCaches( | 996 void ResourcePrefetchPredictor::CreateCaches( |
935 std::unique_ptr<PrefetchDataMap> url_data_map, | 997 std::unique_ptr<PrefetchDataMap> url_data_map, |
936 std::unique_ptr<PrefetchDataMap> host_data_map, | 998 std::unique_ptr<PrefetchDataMap> host_data_map, |
937 std::unique_ptr<RedirectDataMap> url_redirect_data_map, | 999 std::unique_ptr<RedirectDataMap> url_redirect_data_map, |
938 std::unique_ptr<RedirectDataMap> host_redirect_data_map, | 1000 std::unique_ptr<RedirectDataMap> host_redirect_data_map, |
939 std::unique_ptr<ManifestDataMap> manifest_data_map, | 1001 std::unique_ptr<ManifestDataMap> manifest_data_map, |
940 std::unique_ptr<OriginDataMap> origin_data_map) { | 1002 std::unique_ptr<OriginDataMap> origin_data_map) { |
941 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1003 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
942 | 1004 |
943 DCHECK_EQ(INITIALIZING, initialization_state_); | 1005 DCHECK_EQ(INITIALIZING, initialization_state_); |
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1630 } | 1692 } |
1631 } | 1693 } |
1632 | 1694 |
1633 void ResourcePrefetchPredictor::OnManifestFetched( | 1695 void ResourcePrefetchPredictor::OnManifestFetched( |
1634 const std::string& host, | 1696 const std::string& host, |
1635 const precache::PrecacheManifest& manifest) { | 1697 const precache::PrecacheManifest& manifest) { |
1636 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1698 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1637 if (initialization_state_ != INITIALIZED) | 1699 if (initialization_state_ != INITIALIZED) |
1638 return; | 1700 return; |
1639 | 1701 |
1640 if (!config_.is_manifests_enabled) | 1702 if (!config_.is_manifests_enabled || IsManifestTooOld(manifest)) |
1641 return; | 1703 return; |
1642 | 1704 |
1643 // The manifest host has "www." prefix stripped, the manifest host could | 1705 // The manifest host has "www." prefix stripped, the manifest host could |
1644 // correspond to two different hosts in the prefetch database. | 1706 // correspond to two different hosts in the prefetch database. |
1645 UpdatePrefetchDataByManifest(host, PREFETCH_KEY_TYPE_HOST, | 1707 UpdatePrefetchDataByManifest(host, PREFETCH_KEY_TYPE_HOST, |
1646 host_table_cache_.get(), manifest); | 1708 host_table_cache_.get(), manifest); |
1647 UpdatePrefetchDataByManifest("www." + host, PREFETCH_KEY_TYPE_HOST, | 1709 UpdatePrefetchDataByManifest("www." + host, PREFETCH_KEY_TYPE_HOST, |
1648 host_table_cache_.get(), manifest); | 1710 host_table_cache_.get(), manifest); |
1649 | 1711 |
1650 // The manifest is too large to store. | 1712 // The manifest is too large to store. |
(...skipping 30 matching lines...) Expand all Loading... |
1681 | 1743 |
1682 auto resource_entry = data_map->find(key); | 1744 auto resource_entry = data_map->find(key); |
1683 if (resource_entry == data_map->end()) | 1745 if (resource_entry == data_map->end()) |
1684 return; | 1746 return; |
1685 | 1747 |
1686 PrefetchData& data = resource_entry->second; | 1748 PrefetchData& data = resource_entry->second; |
1687 std::map<std::string, int> manifest_index; | 1749 std::map<std::string, int> manifest_index; |
1688 for (int i = 0; i < manifest.resource_size(); ++i) | 1750 for (int i = 0; i < manifest.resource_size(); ++i) |
1689 manifest_index.insert({manifest.resource(i).url(), i}); | 1751 manifest_index.insert({manifest.resource(i).url(), i}); |
1690 | 1752 |
| 1753 base::Optional<std::vector<bool>> not_unused = |
| 1754 precache::GetResourceBitset(manifest, internal::kUnusedRemovedExperiment); |
| 1755 |
1691 bool was_updated = false; | 1756 bool was_updated = false; |
1692 base::Optional<std::vector<bool>> unused_bitset = | 1757 if (not_unused.has_value()) { |
1693 precache::GetResourceBitset(manifest, internal::kUnusedRemovedExperiment); | |
1694 if (unused_bitset.has_value()) { | |
1695 // Remove unused resources from |data|. | 1758 // Remove unused resources from |data|. |
1696 auto new_end = std::remove_if( | 1759 auto new_end = std::remove_if( |
1697 data.mutable_resources()->begin(), data.mutable_resources()->end(), | 1760 data.mutable_resources()->begin(), data.mutable_resources()->end(), |
1698 [&](const ResourceData& x) { | 1761 [&](const ResourceData& x) { |
1699 auto it = manifest_index.find(x.resource_url()); | 1762 auto it = manifest_index.find(x.resource_url()); |
1700 if (it == manifest_index.end()) | 1763 if (it == manifest_index.end()) |
1701 return false; | 1764 return false; |
1702 return !unused_bitset.value()[it->second]; | 1765 return !not_unused.value()[it->second]; |
1703 }); | 1766 }); |
1704 was_updated = new_end != data.mutable_resources()->end(); | 1767 was_updated = new_end != data.mutable_resources()->end(); |
1705 data.mutable_resources()->erase(new_end, data.mutable_resources()->end()); | 1768 data.mutable_resources()->erase(new_end, data.mutable_resources()->end()); |
1706 } | 1769 } |
1707 | 1770 |
1708 if (was_updated) { | 1771 if (was_updated) { |
1709 BrowserThread::PostTask( | 1772 BrowserThread::PostTask( |
1710 BrowserThread::DB, FROM_HERE, | 1773 BrowserThread::DB, FROM_HERE, |
1711 base::Bind(&ResourcePrefetchPredictorTables::UpdateResourceData, | 1774 base::Bind(&ResourcePrefetchPredictorTables::UpdateResourceData, |
1712 tables_, data, key_type)); | 1775 tables_, data, key_type)); |
(...skipping 21 matching lines...) Expand all Loading... |
1734 TestObserver::~TestObserver() { | 1797 TestObserver::~TestObserver() { |
1735 predictor_->SetObserverForTesting(nullptr); | 1798 predictor_->SetObserverForTesting(nullptr); |
1736 } | 1799 } |
1737 | 1800 |
1738 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1801 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
1739 : predictor_(predictor) { | 1802 : predictor_(predictor) { |
1740 predictor_->SetObserverForTesting(this); | 1803 predictor_->SetObserverForTesting(this); |
1741 } | 1804 } |
1742 | 1805 |
1743 } // namespace predictors | 1806 } // namespace predictors |
OLD | NEW |