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