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 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); | 611 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); |
612 OnMainFrameRequest(request); | 612 OnMainFrameRequest(request); |
613 } | 613 } |
614 | 614 |
615 void ResourcePrefetchPredictor::RecordURLResponse( | 615 void ResourcePrefetchPredictor::RecordURLResponse( |
616 const URLRequestSummary& response) { | 616 const URLRequestSummary& response) { |
617 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 617 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
618 if (initialization_state_ != INITIALIZED) | 618 if (initialization_state_ != INITIALIZED) |
619 return; | 619 return; |
620 | 620 |
621 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME) | 621 if (response.resource_type != content::RESOURCE_TYPE_MAIN_FRAME) |
622 OnMainFrameResponse(response); | |
623 else | |
624 OnSubresourceResponse(response); | 622 OnSubresourceResponse(response); |
625 } | 623 } |
626 | 624 |
627 void ResourcePrefetchPredictor::RecordURLRedirect( | 625 void ResourcePrefetchPredictor::RecordURLRedirect( |
628 const URLRequestSummary& response) { | 626 const URLRequestSummary& response) { |
629 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 627 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
630 if (initialization_state_ != INITIALIZED) | 628 if (initialization_state_ != INITIALIZED) |
631 return; | 629 return; |
632 | 630 |
633 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME) | 631 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME) |
(...skipping 27 matching lines...) Expand all Loading... |
661 const base::TimeTicks& first_contentful_paint) { | 659 const base::TimeTicks& first_contentful_paint) { |
662 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 660 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
663 if (initialization_state_ != INITIALIZED) | 661 if (initialization_state_ != INITIALIZED) |
664 return; | 662 return; |
665 | 663 |
666 NavigationMap::iterator nav_it = inflight_navigations_.find(navigation_id); | 664 NavigationMap::iterator nav_it = inflight_navigations_.find(navigation_id); |
667 if (nav_it != inflight_navigations_.end()) | 665 if (nav_it != inflight_navigations_.end()) |
668 nav_it->second->first_contentful_paint = first_contentful_paint; | 666 nav_it->second->first_contentful_paint = first_contentful_paint; |
669 } | 667 } |
670 | 668 |
671 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url, | |
672 HintOrigin origin) { | |
673 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url", | |
674 url.spec()); | |
675 // Save prefetch start time to report prefetching duration. | |
676 if (inflight_prefetches_.find(url) == inflight_prefetches_.end() && | |
677 IsUrlPrefetchable(url)) { | |
678 inflight_prefetches_.insert(std::make_pair(url, base::TimeTicks::Now())); | |
679 } | |
680 | |
681 if (!prefetch_manager_.get()) // Prefetching not enabled. | |
682 return; | |
683 if (!config_.IsPrefetchingEnabledForOrigin(profile_, origin)) | |
684 return; | |
685 | |
686 ResourcePrefetchPredictor::Prediction prediction; | |
687 if (!GetPrefetchData(url, &prediction)) | |
688 return; | |
689 | |
690 BrowserThread::PostTask( | |
691 BrowserThread::IO, FROM_HERE, | |
692 base::BindOnce(&ResourcePrefetcherManager::MaybeAddPrefetch, | |
693 prefetch_manager_, url, prediction.subresource_urls)); | |
694 | |
695 if (observer_) | |
696 observer_->OnPrefetchingStarted(url); | |
697 } | |
698 | |
699 void ResourcePrefetchPredictor::StopPrefetching(const GURL& url) { | |
700 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StopPrefetching", "url", | |
701 url.spec()); | |
702 auto it = inflight_prefetches_.find(url); | |
703 if (it != inflight_prefetches_.end()) { | |
704 UMA_HISTOGRAM_TIMES( | |
705 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, | |
706 base::TimeTicks::Now() - it->second); | |
707 inflight_prefetches_.erase(it); | |
708 } | |
709 if (!prefetch_manager_.get()) // Not enabled. | |
710 return; | |
711 | |
712 BrowserThread::PostTask( | |
713 BrowserThread::IO, FROM_HERE, | |
714 base::BindOnce(&ResourcePrefetcherManager::MaybeRemovePrefetch, | |
715 prefetch_manager_, url)); | |
716 | |
717 if (observer_) | |
718 observer_->OnPrefetchingStopped(url); | |
719 } | |
720 | |
721 void ResourcePrefetchPredictor::OnPrefetchingFinished( | 669 void ResourcePrefetchPredictor::OnPrefetchingFinished( |
722 const GURL& main_frame_url, | 670 const GURL& main_frame_url, |
723 std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) { | 671 std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) { |
724 if (observer_) | 672 if (observer_) |
725 observer_->OnPrefetchingFinished(main_frame_url); | 673 observer_->OnPrefetchingFinished(main_frame_url); |
726 | 674 |
727 prefetcher_stats_.insert(std::make_pair(main_frame_url, std::move(stats))); | 675 prefetcher_stats_.insert(std::make_pair(main_frame_url, std::move(stats))); |
728 } | 676 } |
729 | 677 |
730 bool ResourcePrefetchPredictor::IsUrlPrefetchable(const GURL& main_frame_url) { | 678 bool ResourcePrefetchPredictor::IsUrlPrefetchable( |
| 679 const GURL& main_frame_url) const { |
731 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 680 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
732 if (initialization_state_ != INITIALIZED) | 681 if (initialization_state_ != INITIALIZED) |
733 return false; | 682 return false; |
734 | 683 |
735 return GetPrefetchData(main_frame_url, nullptr); | 684 return GetPrefetchData(main_frame_url, nullptr); |
736 } | 685 } |
737 | 686 |
738 bool ResourcePrefetchPredictor::IsResourcePrefetchable( | 687 bool ResourcePrefetchPredictor::IsResourcePrefetchable( |
739 const ResourceData& resource) const { | 688 const ResourceData& resource) const { |
740 float confidence = static_cast<float>(resource.number_of_hits()) / | 689 float confidence = static_cast<float>(resource.number_of_hits()) / |
(...skipping 13 matching lines...) Expand all Loading... |
754 prefetch_manager_ = NULL; | 703 prefetch_manager_ = NULL; |
755 } | 704 } |
756 history_service_observer_.RemoveAll(); | 705 history_service_observer_.RemoveAll(); |
757 } | 706 } |
758 | 707 |
759 void ResourcePrefetchPredictor::OnMainFrameRequest( | 708 void ResourcePrefetchPredictor::OnMainFrameRequest( |
760 const URLRequestSummary& request) { | 709 const URLRequestSummary& request) { |
761 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 710 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
762 DCHECK_EQ(INITIALIZED, initialization_state_); | 711 DCHECK_EQ(INITIALIZED, initialization_state_); |
763 | 712 |
764 const GURL& main_frame_url = request.navigation_id.main_frame_url; | |
765 StartPrefetching(main_frame_url, HintOrigin::NAVIGATION); | |
766 | |
767 CleanupAbandonedNavigations(request.navigation_id); | 713 CleanupAbandonedNavigations(request.navigation_id); |
768 | 714 |
769 // New empty navigation entry. | 715 // New empty navigation entry. |
770 inflight_navigations_.insert( | 716 const GURL& main_frame_url = request.navigation_id.main_frame_url; |
771 std::make_pair(request.navigation_id, | 717 inflight_navigations_.emplace( |
772 base::MakeUnique<PageRequestSummary>(main_frame_url))); | 718 request.navigation_id, |
773 } | 719 base::MakeUnique<PageRequestSummary>(main_frame_url)); |
774 | |
775 void ResourcePrefetchPredictor::OnMainFrameResponse( | |
776 const URLRequestSummary& response) { | |
777 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
778 DCHECK_EQ(INITIALIZED, initialization_state_); | |
779 | |
780 NavigationMap::iterator nav_it = | |
781 inflight_navigations_.find(response.navigation_id); | |
782 if (nav_it != inflight_navigations_.end()) { | |
783 // To match an URL in StartPrefetching(). | |
784 StopPrefetching(nav_it->second->initial_url); | |
785 } else { | |
786 StopPrefetching(response.navigation_id.main_frame_url); | |
787 } | |
788 } | 720 } |
789 | 721 |
790 void ResourcePrefetchPredictor::OnMainFrameRedirect( | 722 void ResourcePrefetchPredictor::OnMainFrameRedirect( |
791 const URLRequestSummary& response) { | 723 const URLRequestSummary& response) { |
792 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 724 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
793 DCHECK_EQ(INITIALIZED, initialization_state_); | 725 DCHECK_EQ(INITIALIZED, initialization_state_); |
794 | 726 |
795 const GURL& main_frame_url = response.navigation_id.main_frame_url; | 727 const GURL& main_frame_url = response.navigation_id.main_frame_url; |
796 std::unique_ptr<PageRequestSummary> summary; | 728 std::unique_ptr<PageRequestSummary> summary; |
797 NavigationMap::iterator nav_it = | 729 NavigationMap::iterator nav_it = |
(...skipping 10 matching lines...) Expand all Loading... |
808 // If we lost the information about the first hop for some reason. | 740 // If we lost the information about the first hop for some reason. |
809 if (!summary) { | 741 if (!summary) { |
810 summary = base::MakeUnique<PageRequestSummary>(main_frame_url); | 742 summary = base::MakeUnique<PageRequestSummary>(main_frame_url); |
811 } | 743 } |
812 | 744 |
813 // A redirect will not lead to another OnMainFrameRequest call, so record the | 745 // A redirect will not lead to another OnMainFrameRequest call, so record the |
814 // redirect url as a new navigation id and save the initial url. | 746 // redirect url as a new navigation id and save the initial url. |
815 NavigationID navigation_id(response.navigation_id); | 747 NavigationID navigation_id(response.navigation_id); |
816 navigation_id.main_frame_url = response.redirect_url; | 748 navigation_id.main_frame_url = response.redirect_url; |
817 summary->main_frame_url = response.redirect_url; | 749 summary->main_frame_url = response.redirect_url; |
818 inflight_navigations_.insert( | 750 inflight_navigations_.emplace(navigation_id, std::move(summary)); |
819 std::make_pair(navigation_id, std::move(summary))); | |
820 } | 751 } |
821 | 752 |
822 void ResourcePrefetchPredictor::OnSubresourceResponse( | 753 void ResourcePrefetchPredictor::OnSubresourceResponse( |
823 const URLRequestSummary& response) { | 754 const URLRequestSummary& response) { |
824 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 755 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
825 DCHECK_EQ(INITIALIZED, initialization_state_); | 756 DCHECK_EQ(INITIALIZED, initialization_state_); |
826 | 757 |
827 NavigationMap::const_iterator nav_it = | 758 NavigationMap::const_iterator nav_it = |
828 inflight_navigations_.find(response.navigation_id); | 759 inflight_navigations_.find(response.navigation_id); |
829 if (nav_it == inflight_navigations_.end()) | 760 if (nav_it == inflight_navigations_.end()) |
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1092 for (NavigationMap::iterator it = inflight_navigations_.begin(); | 1023 for (NavigationMap::iterator it = inflight_navigations_.begin(); |
1093 it != inflight_navigations_.end();) { | 1024 it != inflight_navigations_.end();) { |
1094 if ((it->first.tab_id == navigation_id.tab_id) || | 1025 if ((it->first.tab_id == navigation_id.tab_id) || |
1095 (time_now - it->first.creation_time > max_navigation_age)) { | 1026 (time_now - it->first.creation_time > max_navigation_age)) { |
1096 inflight_navigations_.erase(it++); | 1027 inflight_navigations_.erase(it++); |
1097 } else { | 1028 } else { |
1098 ++it; | 1029 ++it; |
1099 } | 1030 } |
1100 } | 1031 } |
1101 | 1032 |
1102 for (auto it = inflight_prefetches_.begin(); | |
1103 it != inflight_prefetches_.end();) { | |
1104 base::TimeDelta prefetch_age = time_now - it->second; | |
1105 if (prefetch_age > max_navigation_age) { | |
1106 // It goes to the last bucket meaning that the duration was unlimited. | |
1107 UMA_HISTOGRAM_TIMES( | |
1108 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, | |
1109 prefetch_age); | |
1110 it = inflight_prefetches_.erase(it); | |
1111 } else { | |
1112 ++it; | |
1113 } | |
1114 } | |
1115 | |
1116 // Remove old prefetches that haven't been claimed. | 1033 // Remove old prefetches that haven't been claimed. |
1117 for (auto stats_it = prefetcher_stats_.begin(); | 1034 for (auto stats_it = prefetcher_stats_.begin(); |
1118 stats_it != prefetcher_stats_.end();) { | 1035 stats_it != prefetcher_stats_.end();) { |
1119 if (time_now - stats_it->second->start_time > max_navigation_age) { | 1036 if (time_now - stats_it->second->start_time > max_navigation_age) { |
1120 // No requests -> everything is a miss. | 1037 // No requests -> everything is a miss. |
1121 ReportPrefetchAccuracy(*stats_it->second, | 1038 ReportPrefetchAccuracy(*stats_it->second, |
1122 std::vector<URLRequestSummary>()); | 1039 std::vector<URLRequestSummary>()); |
1123 stats_it = prefetcher_stats_.erase(stats_it); | 1040 stats_it = prefetcher_stats_.erase(stats_it); |
1124 } else { | 1041 } else { |
1125 ++stats_it; | 1042 ++stats_it; |
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1838 if (!history_service) | 1755 if (!history_service) |
1839 return; | 1756 return; |
1840 DCHECK(!history_service_observer_.IsObserving(history_service)); | 1757 DCHECK(!history_service_observer_.IsObserving(history_service)); |
1841 history_service_observer_.Add(history_service); | 1758 history_service_observer_.Add(history_service); |
1842 if (history_service->BackendLoaded()) { | 1759 if (history_service->BackendLoaded()) { |
1843 // HistoryService is already loaded. Continue with Initialization. | 1760 // HistoryService is already loaded. Continue with Initialization. |
1844 OnHistoryAndCacheLoaded(); | 1761 OnHistoryAndCacheLoaded(); |
1845 } | 1762 } |
1846 } | 1763 } |
1847 | 1764 |
| 1765 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url) { |
| 1766 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url", |
| 1767 url.spec()); |
| 1768 if (!prefetch_manager_.get()) // Not enabled. |
| 1769 return; |
| 1770 |
| 1771 ResourcePrefetchPredictor::Prediction prediction; |
| 1772 bool has_data = GetPrefetchData(url, &prediction); |
| 1773 DCHECK(has_data); |
| 1774 |
| 1775 BrowserThread::PostTask( |
| 1776 BrowserThread::IO, FROM_HERE, |
| 1777 base::BindOnce(&ResourcePrefetcherManager::MaybeAddPrefetch, |
| 1778 prefetch_manager_, url, prediction.subresource_urls)); |
| 1779 |
| 1780 if (observer_) |
| 1781 observer_->OnPrefetchingStarted(url); |
| 1782 return; |
| 1783 } |
| 1784 |
| 1785 void ResourcePrefetchPredictor::StopPrefetching(const GURL& url) { |
| 1786 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StopPrefetching", "url", |
| 1787 url.spec()); |
| 1788 if (!prefetch_manager_.get()) // Not enabled. |
| 1789 return; |
| 1790 |
| 1791 BrowserThread::PostTask( |
| 1792 BrowserThread::IO, FROM_HERE, |
| 1793 base::BindOnce(&ResourcePrefetcherManager::MaybeRemovePrefetch, |
| 1794 prefetch_manager_, url)); |
| 1795 |
| 1796 if (observer_) |
| 1797 observer_->OnPrefetchingStopped(url); |
| 1798 } |
| 1799 |
1848 //////////////////////////////////////////////////////////////////////////////// | 1800 //////////////////////////////////////////////////////////////////////////////// |
1849 // TestObserver. | 1801 // TestObserver. |
1850 | 1802 |
1851 TestObserver::~TestObserver() { | 1803 TestObserver::~TestObserver() { |
1852 predictor_->SetObserverForTesting(nullptr); | 1804 predictor_->SetObserverForTesting(nullptr); |
1853 } | 1805 } |
1854 | 1806 |
1855 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1807 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
1856 : predictor_(predictor) { | 1808 : predictor_(predictor) { |
1857 predictor_->SetObserverForTesting(this); | 1809 predictor_->SetObserverForTesting(this); |
1858 } | 1810 } |
1859 | 1811 |
1860 } // namespace predictors | 1812 } // namespace predictors |
OLD | NEW |