| 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 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch, | 500 base::Bind(&ResourcePrefetcherManager::MaybeRemovePrefetch, |
| 501 prefetch_manager_, url)); | 501 prefetch_manager_, url)); |
| 502 } | 502 } |
| 503 | 503 |
| 504 void ResourcePrefetchPredictor::OnPrefetchingFinished( | 504 void ResourcePrefetchPredictor::OnPrefetchingFinished( |
| 505 const GURL& main_frame_url) { | 505 const GURL& main_frame_url) { |
| 506 if (observer_) | 506 if (observer_) |
| 507 observer_->OnPrefetchingFinished(main_frame_url); | 507 observer_->OnPrefetchingFinished(main_frame_url); |
| 508 } | 508 } |
| 509 | 509 |
| 510 bool ResourcePrefetchPredictor::IsUrlPrefetchable(const GURL& main_frame_url) { |
| 511 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 512 if (initialization_state_ != INITIALIZED) |
| 513 return false; |
| 514 |
| 515 return GetPrefetchData(main_frame_url, nullptr); |
| 516 } |
| 517 |
| 510 void ResourcePrefetchPredictor::SetObserverForTesting(TestObserver* observer) { | 518 void ResourcePrefetchPredictor::SetObserverForTesting(TestObserver* observer) { |
| 511 observer_ = observer; | 519 observer_ = observer; |
| 512 } | 520 } |
| 513 | 521 |
| 514 void ResourcePrefetchPredictor::Shutdown() { | 522 void ResourcePrefetchPredictor::Shutdown() { |
| 515 if (prefetch_manager_.get()) { | 523 if (prefetch_manager_.get()) { |
| 516 prefetch_manager_->ShutdownOnUIThread(); | 524 prefetch_manager_->ShutdownOnUIThread(); |
| 517 prefetch_manager_ = NULL; | 525 prefetch_manager_ = NULL; |
| 518 } | 526 } |
| 519 history_service_observer_.RemoveAll(); | 527 history_service_observer_.RemoveAll(); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 617 // Report readiness metric with 20% probability. | 625 // Report readiness metric with 20% probability. |
| 618 if (base::RandInt(1, 5) == 5) { | 626 if (base::RandInt(1, 5) == 5) { |
| 619 history_service->TopHosts( | 627 history_service->TopHosts( |
| 620 kNumSampleHosts, | 628 kNumSampleHosts, |
| 621 base::Bind(&ResourcePrefetchPredictor::ReportDatabaseReadiness, | 629 base::Bind(&ResourcePrefetchPredictor::ReportDatabaseReadiness, |
| 622 AsWeakPtr())); | 630 AsWeakPtr())); |
| 623 } | 631 } |
| 624 } | 632 } |
| 625 | 633 |
| 626 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, | 634 bool ResourcePrefetchPredictor::GetPrefetchData(const GURL& main_frame_url, |
| 627 std::vector<GURL>* urls) { | 635 std::vector<GURL>* urls) const { |
| 628 DCHECK(urls); | 636 DCHECK(!urls || urls->empty()); |
| 629 DCHECK(urls->empty()); | |
| 630 | 637 |
| 631 // Fetch URLs based on a redirect endpoint for URL/host first. | 638 // Fetch URLs based on a redirect endpoint for URL/host first. |
| 632 std::string redirect_endpoint; | 639 std::string redirect_endpoint; |
| 633 if (GetRedirectEndpoint(main_frame_url.spec(), *url_redirect_table_cache_, | 640 if (GetRedirectEndpoint(main_frame_url.spec(), *url_redirect_table_cache_, |
| 634 &redirect_endpoint) && | 641 &redirect_endpoint) && |
| 635 PopulatePrefetcherRequest(redirect_endpoint, *url_table_cache_, urls)) { | 642 PopulatePrefetcherRequest(redirect_endpoint, *url_table_cache_, urls)) { |
| 636 return true; | 643 return true; |
| 637 } | 644 } |
| 638 | 645 |
| 639 if (GetRedirectEndpoint(main_frame_url.host(), *host_redirect_table_cache_, | 646 if (GetRedirectEndpoint(main_frame_url.host(), *host_redirect_table_cache_, |
| 640 &redirect_endpoint) && | 647 &redirect_endpoint) && |
| 641 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { | 648 PopulatePrefetcherRequest(redirect_endpoint, *host_table_cache_, urls)) { |
| 642 return true; | 649 return true; |
| 643 } | 650 } |
| 644 | 651 |
| 645 // Fallback to fetching URLs based on the incoming URL/host. | 652 // Fallback to fetching URLs based on the incoming URL/host. |
| 646 if (PopulatePrefetcherRequest(main_frame_url.spec(), *url_table_cache_, | 653 if (PopulatePrefetcherRequest(main_frame_url.spec(), *url_table_cache_, |
| 647 urls)) { | 654 urls)) { |
| 648 return true; | 655 return true; |
| 649 } | 656 } |
| 650 | 657 |
| 651 return PopulatePrefetcherRequest(main_frame_url.host(), *host_table_cache_, | 658 return PopulatePrefetcherRequest(main_frame_url.host(), *host_table_cache_, |
| 652 urls); | 659 urls); |
| 653 } | 660 } |
| 654 | 661 |
| 655 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( | 662 bool ResourcePrefetchPredictor::PopulatePrefetcherRequest( |
| 656 const std::string& main_frame_key, | 663 const std::string& main_frame_key, |
| 657 const PrefetchDataMap& data_map, | 664 const PrefetchDataMap& data_map, |
| 658 std::vector<GURL>* urls) { | 665 std::vector<GURL>* urls) const { |
| 659 DCHECK(urls); | |
| 660 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); | 666 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); |
| 661 if (it == data_map.end()) | 667 if (it == data_map.end()) |
| 662 return false; | 668 return false; |
| 663 | 669 |
| 664 size_t initial_size = urls->size(); | 670 bool has_prefetchable_resource = false; |
| 665 for (const ResourceData& resource : it->second.resources()) { | 671 for (const ResourceData& resource : it->second.resources()) { |
| 666 if (IsResourcePrefetchable(resource)) | 672 if (IsResourcePrefetchable(resource)) { |
| 667 urls->push_back(GURL(resource.resource_url())); | 673 has_prefetchable_resource = true; |
| 674 if (urls) |
| 675 urls->push_back(GURL(resource.resource_url())); |
| 676 } |
| 668 } | 677 } |
| 669 | 678 |
| 670 return urls->size() > initial_size; | 679 return has_prefetchable_resource; |
| 671 } | 680 } |
| 672 | 681 |
| 673 void ResourcePrefetchPredictor::CreateCaches( | 682 void ResourcePrefetchPredictor::CreateCaches( |
| 674 std::unique_ptr<PrefetchDataMap> url_data_map, | 683 std::unique_ptr<PrefetchDataMap> url_data_map, |
| 675 std::unique_ptr<PrefetchDataMap> host_data_map, | 684 std::unique_ptr<PrefetchDataMap> host_data_map, |
| 676 std::unique_ptr<RedirectDataMap> url_redirect_data_map, | 685 std::unique_ptr<RedirectDataMap> url_redirect_data_map, |
| 677 std::unique_ptr<RedirectDataMap> host_redirect_data_map) { | 686 std::unique_ptr<RedirectDataMap> host_redirect_data_map) { |
| 678 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 687 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 679 | 688 |
| 680 DCHECK_EQ(INITIALIZING, initialization_state_); | 689 DCHECK_EQ(INITIALIZING, initialization_state_); |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1103 const RedirectData& url_redirect_data = | 1112 const RedirectData& url_redirect_data = |
| 1104 is_host ? empty_redirect_data : data; | 1113 is_host ? empty_redirect_data : data; |
| 1105 BrowserThread::PostTask( | 1114 BrowserThread::PostTask( |
| 1106 BrowserThread::DB, FROM_HERE, | 1115 BrowserThread::DB, FROM_HERE, |
| 1107 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, | 1116 base::Bind(&ResourcePrefetchPredictorTables::UpdateData, tables_, |
| 1108 empty_data, empty_data, url_redirect_data, | 1117 empty_data, empty_data, url_redirect_data, |
| 1109 host_redirect_data)); | 1118 host_redirect_data)); |
| 1110 } | 1119 } |
| 1111 } | 1120 } |
| 1112 | 1121 |
| 1113 bool ResourcePrefetchPredictor::IsDataPrefetchable( | |
| 1114 const std::string& main_frame_key, | |
| 1115 const PrefetchDataMap& data_map) const { | |
| 1116 PrefetchDataMap::const_iterator it = data_map.find(main_frame_key); | |
| 1117 if (it == data_map.end()) | |
| 1118 return false; | |
| 1119 | |
| 1120 return std::any_of(it->second.resources().begin(), | |
| 1121 it->second.resources().end(), | |
| 1122 [this](const ResourceData& resource) { | |
| 1123 return IsResourcePrefetchable(resource); | |
| 1124 }); | |
| 1125 } | |
| 1126 | |
| 1127 bool ResourcePrefetchPredictor::IsResourcePrefetchable( | 1122 bool ResourcePrefetchPredictor::IsResourcePrefetchable( |
| 1128 const ResourceData& resource) const { | 1123 const ResourceData& resource) const { |
| 1129 float confidence = static_cast<float>(resource.number_of_hits()) / | 1124 float confidence = static_cast<float>(resource.number_of_hits()) / |
| 1130 (resource.number_of_hits() + resource.number_of_misses()); | 1125 (resource.number_of_hits() + resource.number_of_misses()); |
| 1131 return confidence >= config_.min_resource_confidence_to_trigger_prefetch && | 1126 return confidence >= config_.min_resource_confidence_to_trigger_prefetch && |
| 1132 resource.number_of_hits() >= | 1127 resource.number_of_hits() >= |
| 1133 config_.min_resource_hits_to_trigger_prefetch; | 1128 config_.min_resource_hits_to_trigger_prefetch; |
| 1134 } | 1129 } |
| 1135 | 1130 |
| 1136 void ResourcePrefetchPredictor::ReportDatabaseReadiness( | 1131 void ResourcePrefetchPredictor::ReportDatabaseReadiness( |
| 1137 const history::TopHostsList& top_hosts) const { | 1132 const history::TopHostsList& top_hosts) const { |
| 1138 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1133 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1139 if (top_hosts.size() == 0) | 1134 if (top_hosts.size() == 0) |
| 1140 return; | 1135 return; |
| 1141 | 1136 |
| 1142 size_t count_in_cache = 0; | 1137 size_t count_in_cache = 0; |
| 1143 size_t total_visits = 0; | 1138 size_t total_visits = 0; |
| 1144 for (const std::pair<std::string, int>& top_host : top_hosts) { | 1139 for (const std::pair<std::string, int>& top_host : top_hosts) { |
| 1145 const std::string& host = top_host.first; | 1140 const std::string& host = top_host.first; |
| 1146 total_visits += top_host.second; | 1141 total_visits += top_host.second; |
| 1147 | 1142 |
| 1148 // Hostnames in TopHostsLists are stripped of their 'www.' prefix. We | 1143 // Hostnames in TopHostsLists are stripped of their 'www.' prefix. We |
| 1149 // assume that www.foo.com entry from |host_table_cache_| is also suitable | 1144 // assume that www.foo.com entry from |host_table_cache_| is also suitable |
| 1150 // for foo.com. | 1145 // for foo.com. |
| 1151 if (IsDataPrefetchable(host, *host_table_cache_) || | 1146 if (PopulatePrefetcherRequest(host, *host_table_cache_, nullptr) || |
| 1152 (!base::StartsWith(host, "www.", base::CompareCase::SENSITIVE) && | 1147 (!base::StartsWith(host, "www.", base::CompareCase::SENSITIVE) && |
| 1153 IsDataPrefetchable("www." + host, *host_table_cache_))) { | 1148 PopulatePrefetcherRequest("www." + host, *host_table_cache_, |
| 1149 nullptr))) { |
| 1154 ++count_in_cache; | 1150 ++count_in_cache; |
| 1155 } | 1151 } |
| 1156 } | 1152 } |
| 1157 | 1153 |
| 1158 // Filter users that don't have the rich browsing history. | 1154 // Filter users that don't have the rich browsing history. |
| 1159 if (total_visits > kReportReadinessThreshold) { | 1155 if (total_visits > kReportReadinessThreshold) { |
| 1160 UMA_HISTOGRAM_PERCENTAGE("ResourcePrefetchPredictor.DatabaseReadiness", | 1156 UMA_HISTOGRAM_PERCENTAGE("ResourcePrefetchPredictor.DatabaseReadiness", |
| 1161 100 * count_in_cache / top_hosts.size()); | 1157 100 * count_in_cache / top_hosts.size()); |
| 1162 } | 1158 } |
| 1163 } | 1159 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1212 TestObserver::~TestObserver() { | 1208 TestObserver::~TestObserver() { |
| 1213 predictor_->SetObserverForTesting(nullptr); | 1209 predictor_->SetObserverForTesting(nullptr); |
| 1214 } | 1210 } |
| 1215 | 1211 |
| 1216 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1212 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
| 1217 : predictor_(predictor) { | 1213 : predictor_(predictor) { |
| 1218 predictor_->SetObserverForTesting(this); | 1214 predictor_->SetObserverForTesting(this); |
| 1219 } | 1215 } |
| 1220 | 1216 |
| 1221 } // namespace predictors | 1217 } // namespace predictors |
| OLD | NEW |