| 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 // This is roughly in line with the threshold we use for resource confidence. |
| 970 const float kMinWeight = 0.7f; |
| 971 |
| 972 // Don't prefetch resource if it has false bit in any of the following |
| 973 // bitsets. All bits assumed to be true if an optional has no value. |
| 974 base::Optional<std::vector<bool>> not_unused = |
| 975 precache::GetResourceBitset(manifest, internal::kUnusedRemovedExperiment); |
| 976 base::Optional<std::vector<bool>> not_versioned = precache::GetResourceBitset( |
| 977 manifest, internal::kVersionedRemovedExperiment); |
| 978 base::Optional<std::vector<bool>> not_no_store = precache::GetResourceBitset( |
| 979 manifest, internal::kNoStoreRemovedExperiment); |
| 980 |
| 981 bool has_prefetchable_resource = false; |
| 982 for (int i = 0; i < manifest.resource_size(); ++i) { |
| 983 const precache::PrecacheResource& resource = manifest.resource(i); |
| 984 if (resource.weight_ratio() > kMinWeight && |
| 985 (!not_unused.has_value() || not_unused.value()[i]) && |
| 986 (!not_versioned.has_value() || not_versioned.value()[i]) && |
| 987 (!not_no_store.has_value() || not_no_store.value()[i])) { |
| 988 has_prefetchable_resource = true; |
| 989 if (urls) |
| 990 urls->emplace_back(resource.url()); |
| 991 } |
| 992 } |
| 993 |
| 994 return has_prefetchable_resource; |
| 995 } |
| 996 |
| 934 void ResourcePrefetchPredictor::CreateCaches( | 997 void ResourcePrefetchPredictor::CreateCaches( |
| 935 std::unique_ptr<PrefetchDataMap> url_data_map, | 998 std::unique_ptr<PrefetchDataMap> url_data_map, |
| 936 std::unique_ptr<PrefetchDataMap> host_data_map, | 999 std::unique_ptr<PrefetchDataMap> host_data_map, |
| 937 std::unique_ptr<RedirectDataMap> url_redirect_data_map, | 1000 std::unique_ptr<RedirectDataMap> url_redirect_data_map, |
| 938 std::unique_ptr<RedirectDataMap> host_redirect_data_map, | 1001 std::unique_ptr<RedirectDataMap> host_redirect_data_map, |
| 939 std::unique_ptr<ManifestDataMap> manifest_data_map, | 1002 std::unique_ptr<ManifestDataMap> manifest_data_map, |
| 940 std::unique_ptr<OriginDataMap> origin_data_map) { | 1003 std::unique_ptr<OriginDataMap> origin_data_map) { |
| 941 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1004 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 942 | 1005 |
| 943 DCHECK_EQ(INITIALIZING, initialization_state_); | 1006 DCHECK_EQ(INITIALIZING, initialization_state_); |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1630 } | 1693 } |
| 1631 } | 1694 } |
| 1632 | 1695 |
| 1633 void ResourcePrefetchPredictor::OnManifestFetched( | 1696 void ResourcePrefetchPredictor::OnManifestFetched( |
| 1634 const std::string& host, | 1697 const std::string& host, |
| 1635 const precache::PrecacheManifest& manifest) { | 1698 const precache::PrecacheManifest& manifest) { |
| 1636 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1699 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1637 if (initialization_state_ != INITIALIZED) | 1700 if (initialization_state_ != INITIALIZED) |
| 1638 return; | 1701 return; |
| 1639 | 1702 |
| 1640 if (!config_.is_manifests_enabled) | 1703 if (!config_.is_manifests_enabled || IsManifestTooOld(manifest)) |
| 1641 return; | 1704 return; |
| 1642 | 1705 |
| 1643 // The manifest host has "www." prefix stripped, the manifest host could | 1706 // The manifest host has "www." prefix stripped, the manifest host could |
| 1644 // correspond to two different hosts in the prefetch database. | 1707 // correspond to two different hosts in the prefetch database. |
| 1645 UpdatePrefetchDataByManifest(host, PREFETCH_KEY_TYPE_HOST, | 1708 UpdatePrefetchDataByManifest(host, PREFETCH_KEY_TYPE_HOST, |
| 1646 host_table_cache_.get(), manifest); | 1709 host_table_cache_.get(), manifest); |
| 1647 UpdatePrefetchDataByManifest("www." + host, PREFETCH_KEY_TYPE_HOST, | 1710 UpdatePrefetchDataByManifest("www." + host, PREFETCH_KEY_TYPE_HOST, |
| 1648 host_table_cache_.get(), manifest); | 1711 host_table_cache_.get(), manifest); |
| 1649 | 1712 |
| 1650 // The manifest is too large to store. | 1713 // The manifest is too large to store. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1681 | 1744 |
| 1682 auto resource_entry = data_map->find(key); | 1745 auto resource_entry = data_map->find(key); |
| 1683 if (resource_entry == data_map->end()) | 1746 if (resource_entry == data_map->end()) |
| 1684 return; | 1747 return; |
| 1685 | 1748 |
| 1686 PrefetchData& data = resource_entry->second; | 1749 PrefetchData& data = resource_entry->second; |
| 1687 std::map<std::string, int> manifest_index; | 1750 std::map<std::string, int> manifest_index; |
| 1688 for (int i = 0; i < manifest.resource_size(); ++i) | 1751 for (int i = 0; i < manifest.resource_size(); ++i) |
| 1689 manifest_index.insert({manifest.resource(i).url(), i}); | 1752 manifest_index.insert({manifest.resource(i).url(), i}); |
| 1690 | 1753 |
| 1754 base::Optional<std::vector<bool>> not_unused = |
| 1755 precache::GetResourceBitset(manifest, internal::kUnusedRemovedExperiment); |
| 1756 |
| 1691 bool was_updated = false; | 1757 bool was_updated = false; |
| 1692 base::Optional<std::vector<bool>> unused_bitset = | 1758 if (not_unused.has_value()) { |
| 1693 precache::GetResourceBitset(manifest, internal::kUnusedRemovedExperiment); | |
| 1694 if (unused_bitset.has_value()) { | |
| 1695 // Remove unused resources from |data|. | 1759 // Remove unused resources from |data|. |
| 1696 auto new_end = std::remove_if( | 1760 auto new_end = std::remove_if( |
| 1697 data.mutable_resources()->begin(), data.mutable_resources()->end(), | 1761 data.mutable_resources()->begin(), data.mutable_resources()->end(), |
| 1698 [&](const ResourceData& x) { | 1762 [&](const ResourceData& x) { |
| 1699 auto it = manifest_index.find(x.resource_url()); | 1763 auto it = manifest_index.find(x.resource_url()); |
| 1700 if (it == manifest_index.end()) | 1764 if (it == manifest_index.end()) |
| 1701 return false; | 1765 return false; |
| 1702 return !unused_bitset.value()[it->second]; | 1766 return !not_unused.value()[it->second]; |
| 1703 }); | 1767 }); |
| 1704 was_updated = new_end != data.mutable_resources()->end(); | 1768 was_updated = new_end != data.mutable_resources()->end(); |
| 1705 data.mutable_resources()->erase(new_end, data.mutable_resources()->end()); | 1769 data.mutable_resources()->erase(new_end, data.mutable_resources()->end()); |
| 1706 } | 1770 } |
| 1707 | 1771 |
| 1708 if (was_updated) { | 1772 if (was_updated) { |
| 1709 BrowserThread::PostTask( | 1773 BrowserThread::PostTask( |
| 1710 BrowserThread::DB, FROM_HERE, | 1774 BrowserThread::DB, FROM_HERE, |
| 1711 base::Bind(&ResourcePrefetchPredictorTables::UpdateResourceData, | 1775 base::Bind(&ResourcePrefetchPredictorTables::UpdateResourceData, |
| 1712 tables_, data, key_type)); | 1776 tables_, data, key_type)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1734 TestObserver::~TestObserver() { | 1798 TestObserver::~TestObserver() { |
| 1735 predictor_->SetObserverForTesting(nullptr); | 1799 predictor_->SetObserverForTesting(nullptr); |
| 1736 } | 1800 } |
| 1737 | 1801 |
| 1738 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1802 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
| 1739 : predictor_(predictor) { | 1803 : predictor_(predictor) { |
| 1740 predictor_->SetObserverForTesting(this); | 1804 predictor_->SetObserverForTesting(this); |
| 1741 } | 1805 } |
| 1742 | 1806 |
| 1743 } // namespace predictors | 1807 } // namespace predictors |
| OLD | NEW |