| 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 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch, | 532 base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch, |
| 533 prefetch_manager_, url)); | 533 prefetch_manager_, url)); |
| 534 } | 534 } |
| 535 | 535 |
| 536 void ResourcePrefetchPredictor::OnPrefetchingFinished( | 536 void ResourcePrefetchPredictor::OnPrefetchingFinished( |
| 537 const GURL& main_frame_url) { | 537 const GURL& main_frame_url) { |
| 538 if (observer_) | 538 if (observer_) |
| 539 observer_->OnPrefetchingFinished(main_frame_url); | 539 observer_->OnPrefetchingFinished(main_frame_url); |
| 540 } | 540 } |
| 541 | 541 |
| 542 bool ResourcePrefetchPredictor::IsUrlPrefetchable(const GURL& main_frame_url) { |
| 543 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 544 if (initialization_state_ != INITIALIZED) |
| 545 return false; |
| 546 |
| 547 return GetPrefetchData(main_frame_url, nullptr); |
| 548 } |
| 549 |
| 542 void ResourcePrefetchPredictor::SetObserverForTesting(TestObserver* observer) { | 550 void ResourcePrefetchPredictor::SetObserverForTesting(TestObserver* observer) { |
| 543 observer_ = observer; | 551 observer_ = observer; |
| 544 } | 552 } |
| 545 | 553 |
| 546 void ResourcePrefetchPredictor::Shutdown() { | 554 void ResourcePrefetchPredictor::Shutdown() { |
| 547 if (prefetch_manager_.get()) { | 555 if (prefetch_manager_.get()) { |
| 548 prefetch_manager_->ShutdownOnUIThread(); | 556 prefetch_manager_->ShutdownOnUIThread(); |
| 549 prefetch_manager_ = NULL; | 557 prefetch_manager_ = NULL; |
| 550 } | 558 } |
| 551 history_service_observer_.RemoveAll(); | 559 history_service_observer_.RemoveAll(); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 // Report readiness metric with 20% probability. | 663 // Report readiness metric with 20% probability. |
| 656 if (base::RandInt(1, 5) == 5) { | 664 if (base::RandInt(1, 5) == 5) { |
| 657 history_service->TopHosts( | 665 history_service->TopHosts( |
| 658 kNumSampleHosts, | 666 kNumSampleHosts, |
| 659 base::Bind(&ResourcePrefetchPredictor::ReportDatabaseReadiness, | 667 base::Bind(&ResourcePrefetchPredictor::ReportDatabaseReadiness, |
| 660 AsWeakPtr())); | 668 AsWeakPtr())); |
| 661 } | 669 } |
| 662 } | 670 } |
| 663 | 671 |
| 664 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, | 672 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, |
| 665 std::vector<GURL>* urls) { | 673 std::vector<GURL>* urls) const { |
| 666 DCHECK(urls); | 674 DCHECK(!urls || urls->empty()); |
| 667 DCHECK(urls->empty()); | |
| 668 | 675 |
| 669 // Fetch URLs based on a redirect endpoint for URL/host first. | 676 // Fetch URLs based on a redirect endpoint for URL/host first. |
| 670 std::string redirect_endpoint; | 677 std::string redirect_endpoint; |
| 671 if (GetRedirectEndpoint(main_frame_url.spec(), *url_redirect_table_cache_, | 678 if (GetRedirectEndpoint(main_frame_url.spec(), *url_redirect_table_cache_, |
| 672 &redirect_endpoint) && | 679 &redirect_endpoint) && |
| 673 PopulatePrefetcherRequest(redirect_endpoint, *url_table_cache_, urls)) { | 680 PopulatePrefetcherRequest(redirect_endpoint, *url_table_cache_, urls)) { |
| 674 return true; | 681 return true; |
| 675 } | 682 } |
| 676 | 683 |
| 677 if (GetRedirectEndpoint(main_frame_url.host(), *host_redirect_table_cache_, | 684 if (GetRedirectEndpoint(main_frame_url.host(), *host_redirect_table_cache_, |
| 678 &redirect_endpoint) && | 685 &redirect_endpoint) && |
| 679 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { | 686 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { |
| 680 return true; | 687 return true; |
| 681 } | 688 } |
| 682 | 689 |
| 683 // Fallback to fetching URLs based on the incoming URL/host. | 690 // Fallback to fetching URLs based on the incoming URL/host. |
| 684 if (PopulatePrefetcherRequest(main_frame_url.spec(), *url_table_cache_, | 691 if (PopulatePrefetcherRequest(main_frame_url.spec(), *url_table_cache_, |
| 685 urls)) { | 692 urls)) { |
| 686 return true; | 693 return true; |
| 687 } | 694 } |
| 688 | 695 |
| 689 return PopulatePrefetcherRequest(main_frame_url.host(), *host_table_cache_, | 696 return PopulatePrefetcherRequest(main_frame_url.host(), *host_table_cache_, |
| 690 urls); | 697 urls); |
| 691 } | 698 } |
| 692 | 699 |
| 693 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( | 700 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( |
| 694 const std::string& main_frame_key, | 701 const std::string& main_frame_key, |
| 695 const PrefetchDataMap& data_map, | 702 const PrefetchDataMap& data_map, |
| 696 std::vector<GURL>* urls) { | 703 std::vector<GURL>* urls) const { |
| 697 DCHECK(urls); | |
| 698 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); | 704 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); |
| 699 if (it == data_map.end()) | 705 if (it == data_map.end()) |
| 700 return false; | 706 return false; |
| 701 | 707 |
| 702 size_t initial_size = urls->size(); | 708 bool has_prefetchable_resource = false; |
| 703 for (const ResourceData& resource : it->second.resources()) { | 709 for (const ResourceData& resource : it->second.resources()) { |
| 704 if (IsResourcePrefetchable(resource)) | 710 if (IsResourcePrefetchable(resource)) { |
| 705 urls->push_back(GURL(resource.resource_url())); | 711 has_prefetchable_resource = true; |
| 712 if (urls) |
| 713 urls->push_back(GURL(resource.resource_url())); |
| 714 } |
| 706 } | 715 } |
| 707 | 716 |
| 708 return urls->size() > initial_size; | 717 return has_prefetchable_resource; |
| 709 } | 718 } |
| 710 | 719 |
| 711 void ResourcePrefetchPredictor::CreateCaches( | 720 void ResourcePrefetchPredictor::CreateCaches( |
| 712 std::unique_ptr<PrefetchDataMap> url_data_map, | 721 std::unique_ptr<PrefetchDataMap> url_data_map, |
| 713 std::unique_ptr<PrefetchDataMap> host_data_map, | 722 std::unique_ptr<PrefetchDataMap> host_data_map, |
| 714 std::unique_ptr<RedirectDataMap> url_redirect_data_map, | 723 std::unique_ptr<RedirectDataMap> url_redirect_data_map, |
| 715 std::unique_ptr<RedirectDataMap> host_redirect_data_map) { | 724 std::unique_ptr<RedirectDataMap> host_redirect_data_map) { |
| 716 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 725 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 717 | 726 |
| 718 DCHECK_EQ(INITIALIZING, initialization_state_); | 727 DCHECK_EQ(INITIALIZING, initialization_state_); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 const RedirectData& url_redirect_data = | 1150 const RedirectData& url_redirect_data = |
| 1142 is_host ? empty_redirect_data : data; | 1151 is_host ? empty_redirect_data : data; |
| 1143 BrowserThread::PostTask( | 1152 BrowserThread::PostTask( |
| 1144 BrowserThread::DB, FROM_HERE, | 1153 BrowserThread::DB, FROM_HERE, |
| 1145 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, | 1154 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, |
| 1146 empty_data, empty_data, url_redirect_data, | 1155 empty_data, empty_data, url_redirect_data, |
| 1147 host_redirect_data)); | 1156 host_redirect_data)); |
| 1148 } | 1157 } |
| 1149 } | 1158 } |
| 1150 | 1159 |
| 1151 bool ResourcePrefetchPredictor::IsDataPrefetchable( | |
| 1152 const std::string& main_frame_key, | |
| 1153 const PrefetchDataMap& data_map) const { | |
| 1154 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); | |
| 1155 if (it == data_map.end()) | |
| 1156 return false; | |
| 1157 | |
| 1158 return std::any_of(it->second.resources().begin(), | |
| 1159 it->second.resources().end(), | |
| 1160 [this](const ResourceData& resource) { | |
| 1161 return IsResourcePrefetchable(resource); | |
| 1162 }); | |
| 1163 } | |
| 1164 | |
| 1165 bool ResourcePrefetchPredictor::IsResourcePrefetchable( | 1160 bool ResourcePrefetchPredictor::IsResourcePrefetchable( |
| 1166 const ResourceData& resource) const { | 1161 const ResourceData& resource) const { |
| 1167 float confidence = static_cast<float>(resource.number_of_hits()) / | 1162 float confidence = static_cast<float>(resource.number_of_hits()) / |
| 1168 (resource.number_of_hits() + resource.number_of_misses()); | 1163 (resource.number_of_hits() + resource.number_of_misses()); |
| 1169 return confidence >= config_.min_resource_confidence_to_trigger_prefetch && | 1164 return confidence >= config_.min_resource_confidence_to_trigger_prefetch && |
| 1170 resource.number_of_hits() >= | 1165 resource.number_of_hits() >= |
| 1171 config_.min_resource_hits_to_trigger_prefetch; | 1166 config_.min_resource_hits_to_trigger_prefetch; |
| 1172 } | 1167 } |
| 1173 | 1168 |
| 1174 void ResourcePrefetchPredictor::ReportDatabaseReadiness( | 1169 void ResourcePrefetchPredictor::ReportDatabaseReadiness( |
| 1175 const history::TopHostsList& top_hosts) const { | 1170 const history::TopHostsList& top_hosts) const { |
| 1176 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1171 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1177 if (top_hosts.size() == 0) | 1172 if (top_hosts.size() == 0) |
| 1178 return; | 1173 return; |
| 1179 | 1174 |
| 1180 size_t count_in_cache = 0; | 1175 size_t count_in_cache = 0; |
| 1181 size_t total_visits = 0; | 1176 size_t total_visits = 0; |
| 1182 for (const std::pair<std::string, int>& top_host : top_hosts) { | 1177 for (const std::pair<std::string, int>& top_host : top_hosts) { |
| 1183 const std::string& host = top_host.first; | 1178 const std::string& host = top_host.first; |
| 1184 total_visits += top_host.second; | 1179 total_visits += top_host.second; |
| 1185 | 1180 |
| 1186 // Hostnames in TopHostsLists are stripped of their 'www.' prefix. We | 1181 // Hostnames in TopHostsLists are stripped of their 'www.' prefix. We |
| 1187 // assume that www.foo.com entry from |host_table_cache_| is also suitable | 1182 // assume that www.foo.com entry from |host_table_cache_| is also suitable |
| 1188 // for foo.com. | 1183 // for foo.com. |
| 1189 if (IsDataPrefetchable(host, *host_table_cache_) || | 1184 if (PopulatePrefetcherRequest(host, *host_table_cache_, nullptr) || |
| 1190 (!base::StartsWith(host, "www.", base::CompareCase::SENSITIVE) && | 1185 (!base::StartsWith(host, "www.", base::CompareCase::SENSITIVE) && |
| 1191 IsDataPrefetchable("www." + host, *host_table_cache_))) { | 1186 PopulatePrefetcherRequest("www." + host, *host_table_cache_, |
| 1187 nullptr))) { |
| 1192 ++count_in_cache; | 1188 ++count_in_cache; |
| 1193 } | 1189 } |
| 1194 } | 1190 } |
| 1195 | 1191 |
| 1196 // Filter users that don't have the rich browsing history. | 1192 // Filter users that don't have the rich browsing history. |
| 1197 if (total_visits > kReportReadinessThreshold) { | 1193 if (total_visits > kReportReadinessThreshold) { |
| 1198 UMA_HISTOGRAM_PERCENTAGE("ResourcePrefetchPredictor.DatabaseReadiness", | 1194 UMA_HISTOGRAM_PERCENTAGE("ResourcePrefetchPredictor.DatabaseReadiness", |
| 1199 100 * count_in_cache / top_hosts.size()); | 1195 100 * count_in_cache / top_hosts.size()); |
| 1200 } | 1196 } |
| 1201 } | 1197 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 TestObserver::~TestObserver() { | 1246 TestObserver::~TestObserver() { |
| 1251 predictor_->SetObserverForTesting(nullptr); | 1247 predictor_->SetObserverForTesting(nullptr); |
| 1252 } | 1248 } |
| 1253 | 1249 |
| 1254 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1250 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
| 1255 : predictor_(predictor) { | 1251 : predictor_(predictor) { |
| 1256 predictor_->SetObserverForTesting(this); | 1252 predictor_->SetObserverForTesting(this); |
| 1257 } | 1253 } |
| 1258 | 1254 |
| 1259 } // namespace predictors | 1255 } // namespace predictors |
| OLD | NEW |