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 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); | 621 CHECK_EQ(request.resource_type, content::RESOURCE_TYPE_MAIN_FRAME); |
622 OnMainFrameRequest(request); | 622 OnMainFrameRequest(request); |
623 } | 623 } |
624 | 624 |
625 void ResourcePrefetchPredictor::RecordURLResponse( | 625 void ResourcePrefetchPredictor::RecordURLResponse( |
626 const URLRequestSummary& response) { | 626 const URLRequestSummary& response) { |
627 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 627 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
628 if (initialization_state_ != INITIALIZED) | 628 if (initialization_state_ != INITIALIZED) |
629 return; | 629 return; |
630 | 630 |
631 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME) | 631 if (response.resource_type != content::RESOURCE_TYPE_MAIN_FRAME) |
632 OnMainFrameResponse(response); | |
633 else | |
634 OnSubresourceResponse(response); | 632 OnSubresourceResponse(response); |
635 } | 633 } |
636 | 634 |
637 void ResourcePrefetchPredictor::RecordURLRedirect( | 635 void ResourcePrefetchPredictor::RecordURLRedirect( |
638 const URLRequestSummary& response) { | 636 const URLRequestSummary& response) { |
639 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 637 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
640 if (initialization_state_ != INITIALIZED) | 638 if (initialization_state_ != INITIALIZED) |
641 return; | 639 return; |
642 | 640 |
643 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME) | 641 if (response.resource_type == content::RESOURCE_TYPE_MAIN_FRAME) |
(...skipping 27 matching lines...) Expand all Loading... |
671 const base::TimeTicks& first_contentful_paint) { | 669 const base::TimeTicks& first_contentful_paint) { |
672 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 670 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
673 if (initialization_state_ != INITIALIZED) | 671 if (initialization_state_ != INITIALIZED) |
674 return; | 672 return; |
675 | 673 |
676 NavigationMap::iterator nav_it = inflight_navigations_.find(navigation_id); | 674 NavigationMap::iterator nav_it = inflight_navigations_.find(navigation_id); |
677 if (nav_it != inflight_navigations_.end()) | 675 if (nav_it != inflight_navigations_.end()) |
678 nav_it->second->first_contentful_paint = first_contentful_paint; | 676 nav_it->second->first_contentful_paint = first_contentful_paint; |
679 } | 677 } |
680 | 678 |
681 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url, | |
682 HintOrigin origin) { | |
683 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url", | |
684 url.spec()); | |
685 // Save prefetch start time to report prefetching duration. | |
686 if (inflight_prefetches_.find(url) == inflight_prefetches_.end() && | |
687 IsUrlPrefetchable(url)) { | |
688 inflight_prefetches_.insert(std::make_pair(url, base::TimeTicks::Now())); | |
689 } | |
690 | |
691 if (!prefetch_manager_.get()) // Prefetching not enabled. | |
692 return; | |
693 if (!config_.IsPrefetchingEnabledForOrigin(profile_, origin)) | |
694 return; | |
695 | |
696 ResourcePrefetchPredictor::Prediction prediction; | |
697 if (!GetPrefetchData(url, &prediction)) | |
698 return; | |
699 | |
700 BrowserThread::PostTask( | |
701 BrowserThread::IO, FROM_HERE, | |
702 base::BindOnce(&ResourcePrefetcherManager::MaybeAddPrefetch, | |
703 prefetch_manager_, url, prediction.subresource_urls)); | |
704 | |
705 if (observer_) | |
706 observer_->OnPrefetchingStarted(url); | |
707 } | |
708 | |
709 void ResourcePrefetchPredictor::StopPrefetching(const GURL& url) { | |
710 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StopPrefetching", "url", | |
711 url.spec()); | |
712 auto it = inflight_prefetches_.find(url); | |
713 if (it != inflight_prefetches_.end()) { | |
714 UMA_HISTOGRAM_TIMES( | |
715 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, | |
716 base::TimeTicks::Now() - it->second); | |
717 inflight_prefetches_.erase(it); | |
718 } | |
719 if (!prefetch_manager_.get()) // Not enabled. | |
720 return; | |
721 | |
722 BrowserThread::PostTask( | |
723 BrowserThread::IO, FROM_HERE, | |
724 base::BindOnce(&ResourcePrefetcherManager::MaybeRemovePrefetch, | |
725 prefetch_manager_, url)); | |
726 | |
727 if (observer_) | |
728 observer_->OnPrefetchingStopped(url); | |
729 } | |
730 | |
731 void ResourcePrefetchPredictor::OnPrefetchingFinished( | 679 void ResourcePrefetchPredictor::OnPrefetchingFinished( |
732 const GURL& main_frame_url, | 680 const GURL& main_frame_url, |
733 std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) { | 681 std::unique_ptr<ResourcePrefetcher::PrefetcherStats> stats) { |
734 if (observer_) | 682 if (observer_) |
735 observer_->OnPrefetchingFinished(main_frame_url); | 683 observer_->OnPrefetchingFinished(main_frame_url); |
736 | 684 |
737 prefetcher_stats_.insert(std::make_pair(main_frame_url, std::move(stats))); | 685 prefetcher_stats_.insert(std::make_pair(main_frame_url, std::move(stats))); |
738 } | 686 } |
739 | 687 |
740 bool ResourcePrefetchPredictor::IsUrlPrefetchable(const GURL& main_frame_url) { | 688 bool ResourcePrefetchPredictor::IsUrlPrefetchable( |
| 689 const GURL& main_frame_url) const { |
741 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 690 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
742 if (initialization_state_ != INITIALIZED) | 691 if (initialization_state_ != INITIALIZED) |
743 return false; | 692 return false; |
744 | 693 |
745 return GetPrefetchData(main_frame_url, nullptr); | 694 return GetPrefetchData(main_frame_url, nullptr); |
746 } | 695 } |
747 | 696 |
748 bool ResourcePrefetchPredictor::IsResourcePrefetchable( | 697 bool ResourcePrefetchPredictor::IsResourcePrefetchable( |
749 const ResourceData& resource) const { | 698 const ResourceData& resource) const { |
750 float confidence = static_cast<float>(resource.number_of_hits()) / | 699 float confidence = static_cast<float>(resource.number_of_hits()) / |
(...skipping 13 matching lines...) Expand all Loading... |
764 prefetch_manager_ = NULL; | 713 prefetch_manager_ = NULL; |
765 } | 714 } |
766 history_service_observer_.RemoveAll(); | 715 history_service_observer_.RemoveAll(); |
767 } | 716 } |
768 | 717 |
769 void ResourcePrefetchPredictor::OnMainFrameRequest( | 718 void ResourcePrefetchPredictor::OnMainFrameRequest( |
770 const URLRequestSummary& request) { | 719 const URLRequestSummary& request) { |
771 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 720 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
772 DCHECK_EQ(INITIALIZED, initialization_state_); | 721 DCHECK_EQ(INITIALIZED, initialization_state_); |
773 | 722 |
774 const GURL& main_frame_url = request.navigation_id.main_frame_url; | |
775 StartPrefetching(main_frame_url, HintOrigin::NAVIGATION); | |
776 | |
777 CleanupAbandonedNavigations(request.navigation_id); | 723 CleanupAbandonedNavigations(request.navigation_id); |
778 | 724 |
779 // New empty navigation entry. | 725 // New empty navigation entry. |
780 inflight_navigations_.insert( | 726 const GURL& main_frame_url = request.navigation_id.main_frame_url; |
781 std::make_pair(request.navigation_id, | 727 inflight_navigations_.emplace( |
782 base::MakeUnique<PageRequestSummary>(main_frame_url))); | 728 request.navigation_id, |
783 } | 729 base::MakeUnique<PageRequestSummary>(main_frame_url)); |
784 | |
785 void ResourcePrefetchPredictor::OnMainFrameResponse( | |
786 const URLRequestSummary& response) { | |
787 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
788 DCHECK_EQ(INITIALIZED, initialization_state_); | |
789 | |
790 NavigationMap::iterator nav_it = | |
791 inflight_navigations_.find(response.navigation_id); | |
792 if (nav_it != inflight_navigations_.end()) { | |
793 // To match an URL in StartPrefetching(). | |
794 StopPrefetching(nav_it->second->initial_url); | |
795 } else { | |
796 StopPrefetching(response.navigation_id.main_frame_url); | |
797 } | |
798 } | 730 } |
799 | 731 |
800 void ResourcePrefetchPredictor::OnMainFrameRedirect( | 732 void ResourcePrefetchPredictor::OnMainFrameRedirect( |
801 const URLRequestSummary& response) { | 733 const URLRequestSummary& response) { |
802 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 734 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
803 DCHECK_EQ(INITIALIZED, initialization_state_); | 735 DCHECK_EQ(INITIALIZED, initialization_state_); |
804 | 736 |
805 const GURL& main_frame_url = response.navigation_id.main_frame_url; | 737 const GURL& main_frame_url = response.navigation_id.main_frame_url; |
806 std::unique_ptr<PageRequestSummary> summary; | 738 std::unique_ptr<PageRequestSummary> summary; |
807 NavigationMap::iterator nav_it = | 739 NavigationMap::iterator nav_it = |
(...skipping 10 matching lines...) Expand all Loading... |
818 // If we lost the information about the first hop for some reason. | 750 // If we lost the information about the first hop for some reason. |
819 if (!summary) { | 751 if (!summary) { |
820 summary = base::MakeUnique<PageRequestSummary>(main_frame_url); | 752 summary = base::MakeUnique<PageRequestSummary>(main_frame_url); |
821 } | 753 } |
822 | 754 |
823 // A redirect will not lead to another OnMainFrameRequest call, so record the | 755 // A redirect will not lead to another OnMainFrameRequest call, so record the |
824 // redirect url as a new navigation id and save the initial url. | 756 // redirect url as a new navigation id and save the initial url. |
825 NavigationID navigation_id(response.navigation_id); | 757 NavigationID navigation_id(response.navigation_id); |
826 navigation_id.main_frame_url = response.redirect_url; | 758 navigation_id.main_frame_url = response.redirect_url; |
827 summary->main_frame_url = response.redirect_url; | 759 summary->main_frame_url = response.redirect_url; |
828 inflight_navigations_.insert( | 760 inflight_navigations_.emplace(navigation_id, std::move(summary)); |
829 std::make_pair(navigation_id, std::move(summary))); | |
830 } | 761 } |
831 | 762 |
832 void ResourcePrefetchPredictor::OnSubresourceResponse( | 763 void ResourcePrefetchPredictor::OnSubresourceResponse( |
833 const URLRequestSummary& response) { | 764 const URLRequestSummary& response) { |
834 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 765 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
835 DCHECK_EQ(INITIALIZED, initialization_state_); | 766 DCHECK_EQ(INITIALIZED, initialization_state_); |
836 | 767 |
837 NavigationMap::const_iterator nav_it = | 768 NavigationMap::const_iterator nav_it = |
838 inflight_navigations_.find(response.navigation_id); | 769 inflight_navigations_.find(response.navigation_id); |
839 if (nav_it == inflight_navigations_.end()) | 770 if (nav_it == inflight_navigations_.end()) |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1072 for (NavigationMap::iterator it = inflight_navigations_.begin(); | 1003 for (NavigationMap::iterator it = inflight_navigations_.begin(); |
1073 it != inflight_navigations_.end();) { | 1004 it != inflight_navigations_.end();) { |
1074 if ((it->first.tab_id == navigation_id.tab_id) || | 1005 if ((it->first.tab_id == navigation_id.tab_id) || |
1075 (time_now - it->first.creation_time > max_navigation_age)) { | 1006 (time_now - it->first.creation_time > max_navigation_age)) { |
1076 inflight_navigations_.erase(it++); | 1007 inflight_navigations_.erase(it++); |
1077 } else { | 1008 } else { |
1078 ++it; | 1009 ++it; |
1079 } | 1010 } |
1080 } | 1011 } |
1081 | 1012 |
1082 for (auto it = inflight_prefetches_.begin(); | |
1083 it != inflight_prefetches_.end();) { | |
1084 base::TimeDelta prefetch_age = time_now - it->second; | |
1085 if (prefetch_age > max_navigation_age) { | |
1086 // It goes to the last bucket meaning that the duration was unlimited. | |
1087 UMA_HISTOGRAM_TIMES( | |
1088 internal::kResourcePrefetchPredictorPrefetchingDurationHistogram, | |
1089 prefetch_age); | |
1090 it = inflight_prefetches_.erase(it); | |
1091 } else { | |
1092 ++it; | |
1093 } | |
1094 } | |
1095 | |
1096 // Remove old prefetches that haven't been claimed. | 1013 // Remove old prefetches that haven't been claimed. |
1097 for (auto stats_it = prefetcher_stats_.begin(); | 1014 for (auto stats_it = prefetcher_stats_.begin(); |
1098 stats_it != prefetcher_stats_.end();) { | 1015 stats_it != prefetcher_stats_.end();) { |
1099 if (time_now - stats_it->second->start_time > max_navigation_age) { | 1016 if (time_now - stats_it->second->start_time > max_navigation_age) { |
1100 // No requests -> everything is a miss. | 1017 // No requests -> everything is a miss. |
1101 ReportPrefetchAccuracy(*stats_it->second, | 1018 ReportPrefetchAccuracy(*stats_it->second, |
1102 std::vector<URLRequestSummary>()); | 1019 std::vector<URLRequestSummary>()); |
1103 stats_it = prefetcher_stats_.erase(stats_it); | 1020 stats_it = prefetcher_stats_.erase(stats_it); |
1104 } else { | 1021 } else { |
1105 ++stats_it; | 1022 ++stats_it; |
(...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 if (!history_service) | 1509 if (!history_service) |
1593 return; | 1510 return; |
1594 DCHECK(!history_service_observer_.IsObserving(history_service)); | 1511 DCHECK(!history_service_observer_.IsObserving(history_service)); |
1595 history_service_observer_.Add(history_service); | 1512 history_service_observer_.Add(history_service); |
1596 if (history_service->BackendLoaded()) { | 1513 if (history_service->BackendLoaded()) { |
1597 // HistoryService is already loaded. Continue with Initialization. | 1514 // HistoryService is already loaded. Continue with Initialization. |
1598 OnHistoryAndCacheLoaded(); | 1515 OnHistoryAndCacheLoaded(); |
1599 } | 1516 } |
1600 } | 1517 } |
1601 | 1518 |
| 1519 void ResourcePrefetchPredictor::StartPrefetching(const GURL& url) { |
| 1520 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StartPrefetching", "url", |
| 1521 url.spec()); |
| 1522 if (!prefetch_manager_.get()) // Not enabled. |
| 1523 return; |
| 1524 |
| 1525 ResourcePrefetchPredictor::Prediction prediction; |
| 1526 bool has_data = GetPrefetchData(url, &prediction); |
| 1527 DCHECK(has_data); |
| 1528 |
| 1529 BrowserThread::PostTask( |
| 1530 BrowserThread::IO, FROM_HERE, |
| 1531 base::BindOnce(&ResourcePrefetcherManager::MaybeAddPrefetch, |
| 1532 prefetch_manager_, url, prediction.subresource_urls)); |
| 1533 |
| 1534 if (observer_) |
| 1535 observer_->OnPrefetchingStarted(url); |
| 1536 } |
| 1537 |
| 1538 void ResourcePrefetchPredictor::StopPrefetching(const GURL& url) { |
| 1539 TRACE_EVENT1("browser", "ResourcePrefetchPredictor::StopPrefetching", "url", |
| 1540 url.spec()); |
| 1541 if (!prefetch_manager_.get()) // Not enabled. |
| 1542 return; |
| 1543 |
| 1544 BrowserThread::PostTask( |
| 1545 BrowserThread::IO, FROM_HERE, |
| 1546 base::BindOnce(&ResourcePrefetcherManager::MaybeRemovePrefetch, |
| 1547 prefetch_manager_, url)); |
| 1548 |
| 1549 if (observer_) |
| 1550 observer_->OnPrefetchingStopped(url); |
| 1551 } |
| 1552 |
1602 //////////////////////////////////////////////////////////////////////////////// | 1553 //////////////////////////////////////////////////////////////////////////////// |
1603 // TestObserver. | 1554 // TestObserver. |
1604 | 1555 |
1605 TestObserver::~TestObserver() { | 1556 TestObserver::~TestObserver() { |
1606 predictor_->SetObserverForTesting(nullptr); | 1557 predictor_->SetObserverForTesting(nullptr); |
1607 } | 1558 } |
1608 | 1559 |
1609 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) | 1560 TestObserver::TestObserver(ResourcePrefetchPredictor* predictor) |
1610 : predictor_(predictor) { | 1561 : predictor_(predictor) { |
1611 predictor_->SetObserverForTesting(this); | 1562 predictor_->SetObserverForTesting(this); |
1612 } | 1563 } |
1613 | 1564 |
1614 } // namespace predictors | 1565 } // namespace predictors |
OLD | NEW |