| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/prerender/prerender_manager.h" | 5 #include "chrome/browser/prerender/prerender_manager.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <functional> | 10 #include <functional> |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 }; | 138 }; |
| 139 | 139 |
| 140 // static | 140 // static |
| 141 int PrerenderManager::prerenders_per_session_count_ = 0; | 141 int PrerenderManager::prerenders_per_session_count_ = 0; |
| 142 | 142 |
| 143 // static | 143 // static |
| 144 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = | 144 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = |
| 145 PRERENDER_MODE_ENABLED; | 145 PRERENDER_MODE_ENABLED; |
| 146 | 146 |
| 147 struct PrerenderManager::NavigationRecord { | 147 struct PrerenderManager::NavigationRecord { |
| 148 NavigationRecord(const GURL& url, base::TimeTicks time) | 148 NavigationRecord(const GURL& url, base::TimeTicks time, Origin origin) |
| 149 : url(url), | 149 : url(url), time(time), origin(origin) {} |
| 150 time(time) { | |
| 151 } | |
| 152 | 150 |
| 153 GURL url; | 151 GURL url; |
| 154 base::TimeTicks time; | 152 base::TimeTicks time; |
| 153 Origin origin; |
| 155 }; | 154 }; |
| 156 | 155 |
| 157 PrerenderManager::PrerenderManager(Profile* profile) | 156 PrerenderManager::PrerenderManager(Profile* profile) |
| 158 : profile_(profile), | 157 : profile_(profile), |
| 159 prerender_contents_factory_(PrerenderContents::CreateFactory()), | 158 prerender_contents_factory_(PrerenderContents::CreateFactory()), |
| 160 last_prerender_start_time_( | 159 last_prerender_start_time_( |
| 161 GetCurrentTimeTicks() - | 160 GetCurrentTimeTicks() - |
| 162 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), | 161 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs)), |
| 163 prerender_history_(new PrerenderHistory(kHistoryLength)), | 162 prerender_history_(new PrerenderHistory(kHistoryLength)), |
| 164 histograms_(new PrerenderHistograms()), | 163 histograms_(new PrerenderHistograms()), |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 is_redirect, is_no_store); | 560 is_redirect, is_no_store); |
| 562 } | 561 } |
| 563 | 562 |
| 564 void PrerenderManager::RecordPrefetchRedirectCount(Origin origin, | 563 void PrerenderManager::RecordPrefetchRedirectCount(Origin origin, |
| 565 bool is_main_resource, | 564 bool is_main_resource, |
| 566 int redirect_count) { | 565 int redirect_count) { |
| 567 histograms_->RecordPrefetchRedirectCount(origin, is_main_resource, | 566 histograms_->RecordPrefetchRedirectCount(origin, is_main_resource, |
| 568 redirect_count); | 567 redirect_count); |
| 569 } | 568 } |
| 570 | 569 |
| 570 void PrerenderManager::RecordFirstContentfulPaint(const GURL& url, |
| 571 bool is_no_store, |
| 572 base::TimeDelta time) { |
| 573 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); |
| 574 |
| 575 // Compute the prefetch age. |
| 576 base::TimeDelta prefetch_age; |
| 577 Origin origin = ORIGIN_NONE; |
| 578 for (auto it = prefetches_.crbegin(); it != prefetches_.crend(); ++it) { |
| 579 if (it->url == url) { |
| 580 prefetch_age = GetCurrentTimeTicks() - it->time; |
| 581 origin = it->origin; |
| 582 break; |
| 583 } |
| 584 } |
| 585 |
| 586 histograms_->RecordFirstContentfulPaint(origin, is_no_store, time, |
| 587 prefetch_age); |
| 588 |
| 589 // Loading a prefetched URL resets the revalidation bypass. Remove the url |
| 590 // from the prefetch list for more accurate metrics. |
| 591 prefetches_.erase( |
| 592 std::remove_if(prefetches_.begin(), prefetches_.end(), |
| 593 [url](const NavigationRecord& r) { return r.url == url; }), |
| 594 prefetches_.end()); |
| 595 } |
| 596 |
| 571 // static | 597 // static |
| 572 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { | 598 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { |
| 573 return mode_; | 599 return mode_; |
| 574 } | 600 } |
| 575 | 601 |
| 576 // static | 602 // static |
| 577 void PrerenderManager::SetMode(PrerenderManagerMode mode) { | 603 void PrerenderManager::SetMode(PrerenderManagerMode mode) { |
| 578 mode_ = mode; | 604 mode_ = mode; |
| 579 } | 605 } |
| 580 | 606 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 687 } | 713 } |
| 688 } | 714 } |
| 689 | 715 |
| 690 return result; | 716 return result; |
| 691 } | 717 } |
| 692 | 718 |
| 693 bool PrerenderManager::HasRecentlyBeenNavigatedTo(Origin origin, | 719 bool PrerenderManager::HasRecentlyBeenNavigatedTo(Origin origin, |
| 694 const GURL& url) { | 720 const GURL& url) { |
| 695 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 721 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 696 | 722 |
| 697 CleanUpOldNavigations(); | 723 CleanUpOldNavigations(&navigations_, base::TimeDelta::FromMilliseconds( |
| 724 kNavigationRecordWindowMs)); |
| 698 for (auto it = navigations_.rbegin(); it != navigations_.rend(); ++it) { | 725 for (auto it = navigations_.rbegin(); it != navigations_.rend(); ++it) { |
| 699 if (it->url == url) { | 726 if (it->url == url) { |
| 700 base::TimeDelta delta = GetCurrentTimeTicks() - it->time; | 727 base::TimeDelta delta = GetCurrentTimeTicks() - it->time; |
| 701 histograms_->RecordTimeSinceLastRecentVisit(origin, delta); | 728 histograms_->RecordTimeSinceLastRecentVisit(origin, delta); |
| 702 return true; | 729 return true; |
| 703 } | 730 } |
| 704 } | 731 } |
| 705 | 732 |
| 706 return false; | 733 return false; |
| 707 } | 734 } |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 771 } | 798 } |
| 772 | 799 |
| 773 void PrerenderManager::RecordFinalStatus(Origin origin, | 800 void PrerenderManager::RecordFinalStatus(Origin origin, |
| 774 FinalStatus final_status) const { | 801 FinalStatus final_status) const { |
| 775 histograms_->RecordFinalStatus(origin, final_status); | 802 histograms_->RecordFinalStatus(origin, final_status); |
| 776 } | 803 } |
| 777 | 804 |
| 778 void PrerenderManager::RecordNavigation(const GURL& url) { | 805 void PrerenderManager::RecordNavigation(const GURL& url) { |
| 779 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 806 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 780 | 807 |
| 781 navigations_.push_back(NavigationRecord(url, GetCurrentTimeTicks())); | 808 navigations_.emplace_back(url, GetCurrentTimeTicks(), ORIGIN_NONE); |
| 782 CleanUpOldNavigations(); | 809 CleanUpOldNavigations(&navigations_, base::TimeDelta::FromMilliseconds( |
| 810 kNavigationRecordWindowMs)); |
| 783 } | 811 } |
| 784 | 812 |
| 785 struct PrerenderManager::PrerenderData::OrderByExpiryTime { | 813 struct PrerenderManager::PrerenderData::OrderByExpiryTime { |
| 786 bool operator()(const std::unique_ptr<PrerenderData>& a, | 814 bool operator()(const std::unique_ptr<PrerenderData>& a, |
| 787 const std::unique_ptr<PrerenderData>& b) const { | 815 const std::unique_ptr<PrerenderData>& b) const { |
| 788 return a->expiry_time() < b->expiry_time(); | 816 return a->expiry_time() < b->expiry_time(); |
| 789 } | 817 } |
| 790 }; | 818 }; |
| 791 | 819 |
| 792 PrerenderManager::PrerenderData::PrerenderData( | 820 PrerenderManager::PrerenderData::PrerenderData( |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 952 GetExpiryTimeForNewPrerender(origin))); | 980 GetExpiryTimeForNewPrerender(origin))); |
| 953 if (!prerender_contents_ptr->Init()) { | 981 if (!prerender_contents_ptr->Init()) { |
| 954 DCHECK(active_prerenders_.end() == | 982 DCHECK(active_prerenders_.end() == |
| 955 FindIteratorForPrerenderContents(prerender_contents_ptr)); | 983 FindIteratorForPrerenderContents(prerender_contents_ptr)); |
| 956 return nullptr; | 984 return nullptr; |
| 957 } | 985 } |
| 958 | 986 |
| 959 histograms_->RecordPrerenderStarted(origin); | 987 histograms_->RecordPrerenderStarted(origin); |
| 960 DCHECK(!prerender_contents_ptr->prerendering_has_started()); | 988 DCHECK(!prerender_contents_ptr->prerendering_has_started()); |
| 961 | 989 |
| 990 if (prerender_contents_ptr->prerender_mode() == PREFETCH_ONLY) |
| 991 prefetches_.emplace_back(url, GetCurrentTimeTicks(), origin); |
| 992 |
| 962 std::unique_ptr<PrerenderHandle> prerender_handle = | 993 std::unique_ptr<PrerenderHandle> prerender_handle = |
| 963 base::WrapUnique(new PrerenderHandle(active_prerenders_.back().get())); | 994 base::WrapUnique(new PrerenderHandle(active_prerenders_.back().get())); |
| 964 SortActivePrerenders(); | 995 SortActivePrerenders(); |
| 965 | 996 |
| 966 last_prerender_start_time_ = GetCurrentTimeTicks(); | 997 last_prerender_start_time_ = GetCurrentTimeTicks(); |
| 967 | 998 |
| 968 gfx::Rect contents_bounds = | 999 gfx::Rect contents_bounds = |
| 969 bounds.IsEmpty() ? config_.default_tab_bounds : bounds; | 1000 bounds.IsEmpty() ? config_.default_tab_bounds : bounds; |
| 970 | 1001 |
| 971 prerender_contents_ptr->StartPrerendering(contents_bounds, | 1002 prerender_contents_ptr->StartPrerendering(contents_bounds, |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1124 | 1155 |
| 1125 void PrerenderManager::DeleteOldWebContents() { | 1156 void PrerenderManager::DeleteOldWebContents() { |
| 1126 for (WebContents* web_contents : old_web_contents_list_) { | 1157 for (WebContents* web_contents : old_web_contents_list_) { |
| 1127 // TODO(dominich): should we use Instant Unload Handler here? | 1158 // TODO(dominich): should we use Instant Unload Handler here? |
| 1128 // Or should |old_web_contents_list_| contain unique_ptrs? | 1159 // Or should |old_web_contents_list_| contain unique_ptrs? |
| 1129 delete web_contents; | 1160 delete web_contents; |
| 1130 } | 1161 } |
| 1131 old_web_contents_list_.clear(); | 1162 old_web_contents_list_.clear(); |
| 1132 } | 1163 } |
| 1133 | 1164 |
| 1134 void PrerenderManager::CleanUpOldNavigations() { | 1165 void PrerenderManager::CleanUpOldNavigations( |
| 1166 std::vector<NavigationRecord>* navigations, |
| 1167 base::TimeDelta max_age) { |
| 1135 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1168 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1136 | 1169 |
| 1137 // Cutoff. Navigations before this cutoff can be discarded. | 1170 // Cutoff. Navigations before this cutoff can be discarded. |
| 1138 base::TimeTicks cutoff = GetCurrentTimeTicks() - | 1171 base::TimeTicks cutoff = GetCurrentTimeTicks() - max_age; |
| 1139 base::TimeDelta::FromMilliseconds(kNavigationRecordWindowMs); | 1172 auto it = navigations->begin(); |
| 1140 auto it = navigations_.begin(); | 1173 for (; it != navigations->end(); ++it) { |
| 1141 for (; it != navigations_.end(); ++it) { | |
| 1142 if (it->time > cutoff) | 1174 if (it->time > cutoff) |
| 1143 break; | 1175 break; |
| 1144 } | 1176 } |
| 1145 navigations_.erase(navigations_.begin(), it); | 1177 navigations->erase(navigations->begin(), it); |
| 1146 } | 1178 } |
| 1147 | 1179 |
| 1148 void PrerenderManager::ScheduleDeleteOldWebContents( | 1180 void PrerenderManager::ScheduleDeleteOldWebContents( |
| 1149 std::unique_ptr<WebContents> tab, | 1181 std::unique_ptr<WebContents> tab, |
| 1150 OnCloseWebContentsDeleter* deleter) { | 1182 OnCloseWebContentsDeleter* deleter) { |
| 1151 old_web_contents_list_.push_back(tab.release()); | 1183 old_web_contents_list_.push_back(tab.release()); |
| 1152 PostCleanupTask(); | 1184 PostCleanupTask(); |
| 1153 | 1185 |
| 1154 if (!deleter) | 1186 if (!deleter) |
| 1155 return; | 1187 return; |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 DCHECK_EQ(1u, erased); | 1365 DCHECK_EQ(1u, erased); |
| 1334 } | 1366 } |
| 1335 | 1367 |
| 1336 void PrerenderManager::SetPrerenderContentsFactoryForTest( | 1368 void PrerenderManager::SetPrerenderContentsFactoryForTest( |
| 1337 PrerenderContents::Factory* prerender_contents_factory) { | 1369 PrerenderContents::Factory* prerender_contents_factory) { |
| 1338 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1370 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1339 prerender_contents_factory_.reset(prerender_contents_factory); | 1371 prerender_contents_factory_.reset(prerender_contents_factory); |
| 1340 } | 1372 } |
| 1341 | 1373 |
| 1342 } // namespace prerender | 1374 } // namespace prerender |
| OLD | NEW |