Chromium Code Reviews| 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 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 is_redirect, is_no_store); | 569 is_redirect, is_no_store); |
| 567 } | 570 } |
| 568 | 571 |
| 569 void PrerenderManager::RecordPrefetchRedirectCount(Origin origin, | 572 void PrerenderManager::RecordPrefetchRedirectCount(Origin origin, |
| 570 bool is_main_resource, | 573 bool is_main_resource, |
| 571 int redirect_count) { | 574 int redirect_count) { |
| 572 histograms_->RecordPrefetchRedirectCount(origin, is_main_resource, | 575 histograms_->RecordPrefetchRedirectCount(origin, is_main_resource, |
| 573 redirect_count); | 576 redirect_count); |
| 574 } | 577 } |
| 575 | 578 |
| 576 void PrerenderManager::RecordFirstContentfulPaint(const GURL& url, | 579 void PrerenderManager::RecordNoStateFirstContentfulPaint(const GURL& url, |
| 577 bool is_no_store, | 580 bool is_no_store, |
| 578 base::TimeDelta time) { | 581 bool was_hidden, |
| 579 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); | 582 base::TimeDelta time) { |
| 583 base::TimeDelta prefetch_age; | |
| 584 Origin origin; | |
| 585 GetPrefetchInformation(url, &prefetch_age, &origin); | |
| 580 | 586 |
| 581 // Compute the prefetch age. | 587 histograms_->RecordPrefetchFirstContentfulPaintTime( |
| 588 origin, is_no_store, was_hidden, time, prefetch_age); | |
| 589 | |
| 590 for (auto& observer : observers_) { | |
| 591 observer->OnFirstContentfulPaint(); | |
| 592 } | |
| 593 } | |
| 594 | |
| 595 void PrerenderManager::RecordPrerenderFirstContentfulPaint( | |
| 596 const GURL& url, | |
| 597 content::WebContents* web_contents, | |
| 598 bool is_no_store, | |
| 599 bool was_hidden, | |
| 600 base::TimeTicks first_contentful_paint) { | |
| 601 PrerenderTabHelper* tab_helper = | |
| 602 PrerenderTabHelper::FromWebContents(web_contents); | |
| 603 DCHECK(tab_helper); | |
| 604 | |
| 582 base::TimeDelta prefetch_age; | 605 base::TimeDelta prefetch_age; |
| 583 Origin origin = ORIGIN_NONE; | 606 // The prefetch origin may not be relevant to the prerender. |
| 584 for (auto it = prefetches_.crbegin(); it != prefetches_.crend(); ++it) { | 607 Origin unused_origin; |
| 585 if (it->url == url) { | 608 GetPrefetchInformation(url, &prefetch_age, &unused_origin); |
| 586 prefetch_age = GetCurrentTimeTicks() - it->time; | 609 |
| 587 origin = it->origin; | 610 base::TimeTicks swap_ticks = tab_helper->swap_ticks(); |
| 588 break; | 611 bool fcp_recorded = false; |
| 589 } | 612 if (!swap_ticks.is_null() && !first_contentful_paint.is_null()) { |
| 613 histograms_->RecordPrefetchFirstContentfulPaintTime( | |
| 614 tab_helper->origin(), is_no_store, was_hidden, | |
| 615 first_contentful_paint - swap_ticks, prefetch_age); | |
| 616 fcp_recorded = true; | |
| 590 } | 617 } |
| 618 histograms_->RecordPerceivedFirstContentfulPaintStatus( | |
| 619 tab_helper->origin(), fcp_recorded, was_hidden); | |
|
pasko
2016/12/22 18:22:01
probably asking it the second time (sorry if so):
mattcary
2016/12/23 09:58:15
Yes, according to Bryan, if a page is hidden then
| |
| 591 | 620 |
| 592 histograms_->RecordFirstContentfulPaint(origin, is_no_store, time, | 621 for (auto& observer : observers_) { |
| 593 prefetch_age); | 622 observer->OnFirstContentfulPaint(); |
| 594 | 623 } |
| 595 // Loading a prefetched URL resets the revalidation bypass. Remove the url | |
| 596 // from the prefetch list for more accurate metrics. | |
| 597 prefetches_.erase( | |
| 598 std::remove_if(prefetches_.begin(), prefetches_.end(), | |
| 599 [url](const NavigationRecord& r) { return r.url == url; }), | |
| 600 prefetches_.end()); | |
| 601 } | 624 } |
| 602 | 625 |
| 603 // static | 626 // static |
| 604 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { | 627 PrerenderManager::PrerenderManagerMode PrerenderManager::GetMode() { |
| 605 return mode_; | 628 return mode_; |
| 606 } | 629 } |
| 607 | 630 |
| 608 // static | 631 // static |
| 609 void PrerenderManager::SetMode(PrerenderManagerMode mode) { | 632 void PrerenderManager::SetMode(PrerenderManagerMode mode) { |
| 610 mode_ = mode; | 633 mode_ = mode; |
| (...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1041 base::ElapsedTimer cleanup_timer; | 1064 base::ElapsedTimer cleanup_timer; |
| 1042 | 1065 |
| 1043 // Perform deferred cleanup work. | 1066 // Perform deferred cleanup work. |
| 1044 DeleteOldWebContents(); | 1067 DeleteOldWebContents(); |
| 1045 DeleteOldEntries(); | 1068 DeleteOldEntries(); |
| 1046 if (active_prerenders_.empty()) | 1069 if (active_prerenders_.empty()) |
| 1047 StopSchedulingPeriodicCleanups(); | 1070 StopSchedulingPeriodicCleanups(); |
| 1048 | 1071 |
| 1049 to_delete_prerenders_.clear(); | 1072 to_delete_prerenders_.clear(); |
| 1050 | 1073 |
| 1074 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); | |
| 1075 | |
| 1051 // Measure how long a the various cleanup tasks took. http://crbug.com/305419. | 1076 // Measure how long a the various cleanup tasks took. http://crbug.com/305419. |
| 1052 UMA_HISTOGRAM_TIMES("Prerender.PeriodicCleanupDeleteContentsTime", | 1077 UMA_HISTOGRAM_TIMES("Prerender.PeriodicCleanupDeleteContentsTime", |
| 1053 cleanup_timer.Elapsed()); | 1078 cleanup_timer.Elapsed()); |
| 1054 } | 1079 } |
| 1055 | 1080 |
| 1056 void PrerenderManager::PostCleanupTask() { | 1081 void PrerenderManager::PostCleanupTask() { |
| 1057 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1082 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1058 base::ThreadTaskRunnerHandle::Get()->PostTask( | 1083 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 1059 FROM_HERE, base::Bind(&PrerenderManager::PeriodicCleanup, | 1084 FROM_HERE, base::Bind(&PrerenderManager::PeriodicCleanup, |
| 1060 weak_factory_.GetWeakPtr())); | 1085 weak_factory_.GetWeakPtr())); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1094 void PrerenderManager::SetClockForTesting( | 1119 void PrerenderManager::SetClockForTesting( |
| 1095 std::unique_ptr<base::SimpleTestClock> clock) { | 1120 std::unique_ptr<base::SimpleTestClock> clock) { |
| 1096 clock_ = std::move(clock); | 1121 clock_ = std::move(clock); |
| 1097 } | 1122 } |
| 1098 | 1123 |
| 1099 void PrerenderManager::SetTickClockForTesting( | 1124 void PrerenderManager::SetTickClockForTesting( |
| 1100 std::unique_ptr<base::SimpleTestTickClock> tick_clock) { | 1125 std::unique_ptr<base::SimpleTestTickClock> tick_clock) { |
| 1101 tick_clock_ = std::move(tick_clock); | 1126 tick_clock_ = std::move(tick_clock); |
| 1102 } | 1127 } |
| 1103 | 1128 |
| 1129 void PrerenderManager::AddObserver( | |
| 1130 std::unique_ptr<PrerenderManagerObserver> observer) { | |
| 1131 observers_.push_back(std::move(observer)); | |
| 1132 } | |
| 1133 | |
| 1104 std::unique_ptr<PrerenderContents> PrerenderManager::CreatePrerenderContents( | 1134 std::unique_ptr<PrerenderContents> PrerenderManager::CreatePrerenderContents( |
| 1105 const GURL& url, | 1135 const GURL& url, |
| 1106 const content::Referrer& referrer, | 1136 const content::Referrer& referrer, |
| 1107 Origin origin) { | 1137 Origin origin) { |
| 1108 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1138 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1109 return base::WrapUnique(prerender_contents_factory_->CreatePrerenderContents( | 1139 return base::WrapUnique(prerender_contents_factory_->CreatePrerenderContents( |
| 1110 this, profile_, url, referrer, origin)); | 1140 this, profile_, url, referrer, origin)); |
| 1111 } | 1141 } |
| 1112 | 1142 |
| 1113 void PrerenderManager::SortActivePrerenders() { | 1143 void PrerenderManager::SortActivePrerenders() { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1156 | 1186 |
| 1157 void PrerenderManager::DeleteOldWebContents() { | 1187 void PrerenderManager::DeleteOldWebContents() { |
| 1158 for (WebContents* web_contents : old_web_contents_list_) { | 1188 for (WebContents* web_contents : old_web_contents_list_) { |
| 1159 // TODO(dominich): should we use Instant Unload Handler here? | 1189 // TODO(dominich): should we use Instant Unload Handler here? |
| 1160 // Or should |old_web_contents_list_| contain unique_ptrs? | 1190 // Or should |old_web_contents_list_| contain unique_ptrs? |
| 1161 delete web_contents; | 1191 delete web_contents; |
| 1162 } | 1192 } |
| 1163 old_web_contents_list_.clear(); | 1193 old_web_contents_list_.clear(); |
| 1164 } | 1194 } |
| 1165 | 1195 |
| 1196 void PrerenderManager::GetPrefetchInformation(const GURL& url, | |
| 1197 base::TimeDelta* prefetch_age, | |
| 1198 Origin* origin) { | |
| 1199 DCHECK(prefetch_age); | |
| 1200 DCHECK(origin); | |
| 1201 CleanUpOldNavigations(&prefetches_, base::TimeDelta::FromMinutes(30)); | |
| 1202 | |
| 1203 *prefetch_age = base::TimeDelta(); | |
| 1204 *origin = ORIGIN_NONE; | |
| 1205 for (auto it = prefetches_.crbegin(); it != prefetches_.crend(); ++it) { | |
| 1206 if (it->url == url) { | |
| 1207 *prefetch_age = GetCurrentTimeTicks() - it->time; | |
| 1208 *origin = it->origin; | |
| 1209 break; | |
| 1210 } | |
| 1211 } | |
| 1212 | |
| 1213 // Loading a prefetched URL resets the revalidation bypass. Remove all | |
| 1214 // matching urls from the prefetch list for more accurate metrics. | |
| 1215 prefetches_.erase( | |
| 1216 std::remove_if(prefetches_.begin(), prefetches_.end(), | |
| 1217 [url](const NavigationRecord& r) { return r.url == url; }), | |
| 1218 prefetches_.end()); | |
| 1219 } | |
| 1220 | |
| 1166 void PrerenderManager::CleanUpOldNavigations( | 1221 void PrerenderManager::CleanUpOldNavigations( |
| 1167 std::vector<NavigationRecord>* navigations, | 1222 std::vector<NavigationRecord>* navigations, |
| 1168 base::TimeDelta max_age) { | 1223 base::TimeDelta max_age) { |
| 1169 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1224 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1170 | 1225 |
| 1171 // Cutoff. Navigations before this cutoff can be discarded. | 1226 // Cutoff. Navigations before this cutoff can be discarded. |
| 1172 base::TimeTicks cutoff = GetCurrentTimeTicks() - max_age; | 1227 base::TimeTicks cutoff = GetCurrentTimeTicks() - max_age; |
| 1173 auto it = navigations->begin(); | 1228 auto it = navigations->begin(); |
| 1174 for (; it != navigations->end(); ++it) { | 1229 for (; it != navigations->end(); ++it) { |
| 1175 if (it->time > cutoff) | 1230 if (it->time > cutoff) |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1370 return weak_factory_.GetWeakPtr(); | 1425 return weak_factory_.GetWeakPtr(); |
| 1371 } | 1426 } |
| 1372 | 1427 |
| 1373 void PrerenderManager::SetPrerenderContentsFactoryForTest( | 1428 void PrerenderManager::SetPrerenderContentsFactoryForTest( |
| 1374 PrerenderContents::Factory* prerender_contents_factory) { | 1429 PrerenderContents::Factory* prerender_contents_factory) { |
| 1375 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 1430 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 1376 prerender_contents_factory_.reset(prerender_contents_factory); | 1431 prerender_contents_factory_.reset(prerender_contents_factory); |
| 1377 } | 1432 } |
| 1378 | 1433 |
| 1379 } // namespace prerender | 1434 } // namespace prerender |
| OLD | NEW |