| 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 // |this| is deleted at this point. | 150 // |this| is deleted at this point. |
| 151 } | 151 } |
| 152 | 152 |
| 153 PrerenderManager* const manager_; | 153 PrerenderManager* const manager_; |
| 154 std::unique_ptr<WebContents> tab_; | 154 std::unique_ptr<WebContents> tab_; |
| 155 bool suppressed_dialog_; | 155 bool suppressed_dialog_; |
| 156 | 156 |
| 157 DISALLOW_COPY_AND_ASSIGN(OnCloseWebContentsDeleter); | 157 DISALLOW_COPY_AND_ASSIGN(OnCloseWebContentsDeleter); |
| 158 }; | 158 }; |
| 159 | 159 |
| 160 PrerenderManagerObserver::~PrerenderManagerObserver() {} |
| 161 |
| 160 // static | 162 // static |
| 161 int PrerenderManager::prerenders_per_session_count_ = 0; | 163 int PrerenderManager::prerenders_per_session_count_ = 0; |
| 162 | 164 |
| 163 // static | 165 // static |
| 164 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = | 166 PrerenderManager::PrerenderManagerMode PrerenderManager::mode_ = |
| 165 PRERENDER_MODE_ENABLED; | 167 PRERENDER_MODE_ENABLED; |
| 166 | 168 |
| 167 struct PrerenderManager::NavigationRecord { | 169 struct PrerenderManager::NavigationRecord { |
| 168 NavigationRecord(const GURL& url, base::TimeTicks time, Origin origin) | 170 NavigationRecord(const GURL& url, base::TimeTicks time, Origin origin) |
| 169 : url(url), time(time), origin(origin) {} | 171 : url(url), time(time), origin(origin) {} |
| 170 | 172 |
| 171 GURL url; | 173 GURL url; |
| 172 base::TimeTicks time; | 174 base::TimeTicks time; |
| 173 Origin origin; | 175 Origin origin; |
| 174 }; | 176 }; |
| 175 | 177 |
| 176 PrerenderManager::PrerenderManager(Profile* profile) | 178 PrerenderManager::PrerenderManager(Profile* profile) |
| 177 : profile_(profile), | 179 : profile_(profile), |
| 178 prerender_contents_factory_(PrerenderContents::CreateFactory()), | 180 prerender_contents_factory_(PrerenderContents::CreateFactory()), |
| 179 prerender_history_(new PrerenderHistory(kHistoryLength)), | 181 prerender_history_(new PrerenderHistory(kHistoryLength)), |
| 180 histograms_(new PrerenderHistograms()), | 182 histograms_(new PrerenderHistograms()), |
| 181 profile_network_bytes_(0), | 183 profile_network_bytes_(0), |
| 182 last_recorded_profile_network_bytes_(0), | 184 last_recorded_profile_network_bytes_(0), |
| 183 clock_(new base::DefaultClock()), | 185 clock_(new base::DefaultClock()), |
| 184 tick_clock_(new base::DefaultTickClock()), | 186 tick_clock_(new base::DefaultTickClock()), |
| 187 page_load_metric_observer_disabled_(false), |
| 185 weak_factory_(this) { | 188 weak_factory_(this) { |
| 186 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 189 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 187 | 190 |
| 188 last_prerender_start_time_ = | 191 last_prerender_start_time_ = |
| 189 GetCurrentTimeTicks() - | 192 GetCurrentTimeTicks() - |
| 190 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); | 193 base::TimeDelta::FromMilliseconds(kMinTimeBetweenPrerendersMs); |
| 191 | 194 |
| 192 notification_registrar_.Add( | 195 notification_registrar_.Add( |
| 193 this, chrome::NOTIFICATION_PROFILE_DESTROYED, | 196 this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 194 content::Source<Profile>(profile_)); | 197 content::Source<Profile>(profile_)); |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 is_redirect, is_no_store); | 561 is_redirect, is_no_store); |
| 559 } | 562 } |
| 560 | 563 |
| 561 void PrerenderManager::RecordPrefetchRedirectCount(Origin origin, | 564 void PrerenderManager::RecordPrefetchRedirectCount(Origin origin, |
| 562 bool is_main_resource, | 565 bool is_main_resource, |
| 563 int redirect_count) { | 566 int redirect_count) { |
| 564 histograms_->RecordPrefetchRedirectCount(origin, is_main_resource, | 567 histograms_->RecordPrefetchRedirectCount(origin, is_main_resource, |
| 565 redirect_count); | 568 redirect_count); |
| 566 } | 569 } |
| 567 | 570 |
| 568 void PrerenderManager::RecordFirstContentfulPaint(const GURL& url, | 571 void PrerenderManager::RecordNoStateFirstContentfulPaint(const GURL& url, |
| 569 bool is_no_store, | 572 bool is_no_store, |
| 570 base::TimeDelta time) { | 573 bool was_hidden, |
| 571 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); | 574 base::TimeDelta time) { |
| 575 base::TimeDelta prefetch_age; |
| 576 Origin origin; |
| 577 GetPrefetchInformation(url, &prefetch_age, &origin); |
| 572 | 578 |
| 573 // Compute the prefetch age. | 579 histograms_->RecordPrefetchFirstContentfulPaintTime( |
| 580 origin, is_no_store, was_hidden, time, prefetch_age); |
| 581 |
| 582 for (auto& observer : observers_) { |
| 583 observer->OnFirstContentfulPaint(); |
| 584 } |
| 585 } |
| 586 |
| 587 void PrerenderManager::RecordPrerenderFirstContentfulPaint( |
| 588 const GURL& url, |
| 589 content::WebContents* web_contents, |
| 590 bool is_no_store, |
| 591 bool was_hidden, |
| 592 base::TimeTicks first_contentful_paint) { |
| 593 DCHECK(!first_contentful_paint.is_null()); |
| 594 |
| 595 PrerenderTabHelper* tab_helper = |
| 596 PrerenderTabHelper::FromWebContents(web_contents); |
| 597 DCHECK(tab_helper); |
| 598 |
| 574 base::TimeDelta prefetch_age; | 599 base::TimeDelta prefetch_age; |
| 575 Origin origin = ORIGIN_NONE; | 600 // The origin at prefetch is superceeded by the tab_helper origin for the |
| 576 for (auto it = prefetches_.crbegin(); it != prefetches_.crend(); ++it) { | 601 // histogram recording, below. |
| 577 if (it->url == url) { | 602 Origin unused_origin; |
| 578 prefetch_age = GetCurrentTimeTicks() - it->time; | 603 GetPrefetchInformation(url, &prefetch_age, &unused_origin); |
| 579 origin = it->origin; | 604 |
| 580 break; | 605 base::TimeTicks swap_ticks = tab_helper->swap_ticks(); |
| 581 } | 606 bool fcp_recorded = false; |
| 607 if (!swap_ticks.is_null() && !first_contentful_paint.is_null()) { |
| 608 histograms_->RecordPrefetchFirstContentfulPaintTime( |
| 609 tab_helper->origin(), is_no_store, was_hidden, |
| 610 first_contentful_paint - swap_ticks, prefetch_age); |
| 611 fcp_recorded = true; |
| 582 } | 612 } |
| 613 histograms_->RecordPerceivedFirstContentfulPaintStatus( |
| 614 tab_helper->origin(), fcp_recorded, was_hidden); |
| 583 | 615 |
| 584 histograms_->RecordFirstContentfulPaint(origin, is_no_store, time, | 616 for (auto& observer : observers_) { |
| 585 prefetch_age); | 617 observer->OnFirstContentfulPaint(); |
| 586 | 618 } |
| 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 } | 619 } |
| 594 | 620 |
| 595 // static | 621 // static |
| 596 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { | 622 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { |
| 597 return mode_; | 623 return mode_; |
| 598 } | 624 } |
| 599 | 625 |
| 600 // static | 626 // static |
| 601 void PrerenderManager::SetMode(PrerenderManagerMode mode) { | 627 void PrerenderManager::SetMode(PrerenderManagerMode mode) { |
| 602 mode_ = mode; | 628 mode_ = mode; |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 base::ElapsedTimer cleanup_timer; | 1059 base::ElapsedTimer cleanup_timer; |
| 1034 | 1060 |
| 1035 // Perform deferred cleanup work. | 1061 // Perform deferred cleanup work. |
| 1036 DeleteOldWebContents(); | 1062 DeleteOldWebContents(); |
| 1037 DeleteOldEntries(); | 1063 DeleteOldEntries(); |
| 1038 if (active_prerenders_.empty()) | 1064 if (active_prerenders_.empty()) |
| 1039 StopSchedulingPeriodicCleanups(); | 1065 StopSchedulingPeriodicCleanups(); |
| 1040 | 1066 |
| 1041 to_delete_prerenders_.clear(); | 1067 to_delete_prerenders_.clear(); |
| 1042 | 1068 |
| 1069 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); |
| 1070 |
| 1043 // Measure how long a the various cleanup tasks took. http://crbug.com/305419. | 1071 // Measure how long a the various cleanup tasks took. http://crbug.com/305419. |
| 1044 UMA_HISTOGRAM_TIMES("Prerender.PeriodicCleanupDeleteContentsTime", | 1072 UMA_HISTOGRAM_TIMES("Prerender.PeriodicCleanupDeleteContentsTime", |
| 1045 cleanup_timer.Elapsed()); | 1073 cleanup_timer.Elapsed()); |
| 1046 } | 1074 } |
| 1047 | 1075 |
| 1048 void PrerenderManager::PostCleanupTask() { | 1076 void PrerenderManager::PostCleanupTask() { |
| 1049 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1077 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1050 base::ThreadTaskRunnerHandle::Get()->PostTask( | 1078 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 1051 FROM_HERE, base::Bind(&PrerenderManager::PeriodicCleanup, | 1079 FROM_HERE, base::Bind(&PrerenderManager::PeriodicCleanup, |
| 1052 weak_factory_.GetWeakPtr())); | 1080 weak_factory_.GetWeakPtr())); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1086 void PrerenderManager::SetClockForTesting( | 1114 void PrerenderManager::SetClockForTesting( |
| 1087 std::unique_ptr<base::SimpleTestClock> clock) { | 1115 std::unique_ptr<base::SimpleTestClock> clock) { |
| 1088 clock_ = std::move(clock); | 1116 clock_ = std::move(clock); |
| 1089 } | 1117 } |
| 1090 | 1118 |
| 1091 void PrerenderManager::SetTickClockForTesting( | 1119 void PrerenderManager::SetTickClockForTesting( |
| 1092 std::unique_ptr<base::SimpleTestTickClock> tick_clock) { | 1120 std::unique_ptr<base::SimpleTestTickClock> tick_clock) { |
| 1093 tick_clock_ = std::move(tick_clock); | 1121 tick_clock_ = std::move(tick_clock); |
| 1094 } | 1122 } |
| 1095 | 1123 |
| 1124 void PrerenderManager::AddObserver( |
| 1125 std::unique_ptr<PrerenderManagerObserver> observer) { |
| 1126 observers_.push_back(std::move(observer)); |
| 1127 } |
| 1128 |
| 1096 std::unique_ptr<PrerenderContents> PrerenderManager::CreatePrerenderContents( | 1129 std::unique_ptr<PrerenderContents> PrerenderManager::CreatePrerenderContents( |
| 1097 const GURL& url, | 1130 const GURL& url, |
| 1098 const content::Referrer& referrer, | 1131 const content::Referrer& referrer, |
| 1099 Origin origin) { | 1132 Origin origin) { |
| 1100 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1133 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1101 return base::WrapUnique(prerender_contents_factory_->CreatePrerenderContents( | 1134 return base::WrapUnique(prerender_contents_factory_->CreatePrerenderContents( |
| 1102 this, profile_, url, referrer, origin)); | 1135 this, profile_, url, referrer, origin)); |
| 1103 } | 1136 } |
| 1104 | 1137 |
| 1105 void PrerenderManager::SortActivePrerenders() { | 1138 void PrerenderManager::SortActivePrerenders() { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1148 | 1181 |
| 1149 void PrerenderManager::DeleteOldWebContents() { | 1182 void PrerenderManager::DeleteOldWebContents() { |
| 1150 for (WebContents* web_contents : old_web_contents_list_) { | 1183 for (WebContents* web_contents : old_web_contents_list_) { |
| 1151 // TODO(dominich): should we use Instant Unload Handler here? | 1184 // TODO(dominich): should we use Instant Unload Handler here? |
| 1152 // Or should |old_web_contents_list_| contain unique_ptrs? | 1185 // Or should |old_web_contents_list_| contain unique_ptrs? |
| 1153 delete web_contents; | 1186 delete web_contents; |
| 1154 } | 1187 } |
| 1155 old_web_contents_list_.clear(); | 1188 old_web_contents_list_.clear(); |
| 1156 } | 1189 } |
| 1157 | 1190 |
| 1191 void PrerenderManager::GetPrefetchInformation(const GURL& url, |
| 1192 base::TimeDelta* prefetch_age, |
| 1193 Origin* origin) { |
| 1194 DCHECK(prefetch_age); |
| 1195 DCHECK(origin); |
| 1196 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); |
| 1197 |
| 1198 *prefetch_age = base::TimeDelta(); |
| 1199 *origin = ORIGIN_NONE; |
| 1200 for (auto it = prefetches_.crbegin(); it != prefetches_.crend(); ++it) { |
| 1201 if (it->url == url) { |
| 1202 *prefetch_age = GetCurrentTimeTicks() - it->time; |
| 1203 *origin = it->origin; |
| 1204 break; |
| 1205 } |
| 1206 } |
| 1207 |
| 1208 // Loading a prefetched URL resets the revalidation bypass. Remove all |
| 1209 // matching urls from the prefetch list for more accurate metrics. |
| 1210 prefetches_.erase( |
| 1211 std::remove_if(prefetches_.begin(), prefetches_.end(), |
| 1212 [url](const NavigationRecord& r) { return r.url == url; }), |
| 1213 prefetches_.end()); |
| 1214 } |
| 1215 |
| 1158 void PrerenderManager::CleanUpOldNavigations( | 1216 void PrerenderManager::CleanUpOldNavigations( |
| 1159 std::vector<NavigationRecord>* navigations, | 1217 std::vector<NavigationRecord>* navigations, |
| 1160 base::TimeDelta max_age) { | 1218 base::TimeDelta max_age) { |
| 1161 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1219 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1162 | 1220 |
| 1163 // Cutoff. Navigations before this cutoff can be discarded. | 1221 // Cutoff. Navigations before this cutoff can be discarded. |
| 1164 base::TimeTicks cutoff = GetCurrentTimeTicks() - max_age; | 1222 base::TimeTicks cutoff = GetCurrentTimeTicks() - max_age; |
| 1165 auto it = navigations->begin(); | 1223 auto it = navigations->begin(); |
| 1166 for (; it != navigations->end(); ++it) { | 1224 for (; it != navigations->end(); ++it) { |
| 1167 if (it->time > cutoff) | 1225 if (it->time > cutoff) |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1362 return weak_factory_.GetWeakPtr(); | 1420 return weak_factory_.GetWeakPtr(); |
| 1363 } | 1421 } |
| 1364 | 1422 |
| 1365 void PrerenderManager::SetPrerenderContentsFactoryForTest( | 1423 void PrerenderManager::SetPrerenderContentsFactoryForTest( |
| 1366 PrerenderContents::Factory* prerender_contents_factory) { | 1424 PrerenderContents::Factory* prerender_contents_factory) { |
| 1367 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1425 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1368 prerender_contents_factory_.reset(prerender_contents_factory); | 1426 prerender_contents_factory_.reset(prerender_contents_factory); |
| 1369 } | 1427 } |
| 1370 | 1428 |
| 1371 } // namespace prerender | 1429 } // namespace prerender |
| OLD | NEW |