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